From afe109acf8ad8b3977c100c09ea40236cb848e20 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 31 Oct 2023 12:02:29 -0600 Subject: [PATCH 01/35] client side handling of exit-status packet --- apps/wolfssh/wolfssh.c | 5 +++++ examples/client/client.c | 5 +++++ src/internal.c | 34 ++++++++++++++++++++++++++++++++++ src/ssh.c | 13 +++++++++++++ wolfssh/internal.h | 3 +++ wolfssh/ssh.h | 1 + 6 files changed, 61 insertions(+) diff --git a/apps/wolfssh/wolfssh.c b/apps/wolfssh/wolfssh.c index 9448e3f34..0b6e1ba03 100644 --- a/apps/wolfssh/wolfssh.c +++ b/apps/wolfssh/wolfssh.c @@ -1104,6 +1104,11 @@ static THREAD_RETURN WOLFSSH_THREAD wolfSSH_Client(void* args) } } WCLOSESOCKET(sockFd); + +#if defined(WOLFSSH_TERM) || defined(WOLFSH_SHELL) + ((func_args*)args)->return_code = wolfSSH_GetExitStatus(ssh); +#endif + wolfSSH_free(ssh); wolfSSH_CTX_free(ctx); if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E) diff --git a/examples/client/client.c b/examples/client/client.c index b1f523881..25c3a5cd6 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -987,6 +987,11 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) } } WCLOSESOCKET(sockFd); + +#if defined(WOLFSSH_TERM) || defined(WOLFSH_SHELL) + ((func_args*)args)->return_code = wolfSSH_GetExitStatus(ssh); +#endif + wolfSSH_free(ssh); wolfSSH_CTX_free(ctx); if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E) diff --git a/src/internal.c b/src/internal.c index 5d708f7b3..4e69277fb 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7542,6 +7542,40 @@ static int DoChannelRequest(WOLFSSH* ssh, } } #endif /* WOLFSSH_SHELL && WOLFSSH_TERM */ +#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) + else if (WSTRNCMP(type, "exit-status", typeSz) == 0) { + ret = GetUint32(&ssh->exitStatus, buf, len, &begin); + WLOG(WS_LOG_AGENT, "Got exit status %u.", ssh->exitStatus); + } + else if (WSTRNCMP(type, "exit-signal", typeSz) == 0) { + char sig[WOLFSSH_MAX_NAMESZ]; + word32 sigSz; + byte coreDumped; + + WLOG(WS_LOG_AGENT, "Got exit signal, remote command terminated"); + + sigSz = WOLFSSH_MAX_NAMESZ; + ret = GetString(sig, &sigSz, buf, len, &begin); + if (ret == WS_SUCCESS) { + WLOG(WS_LOG_AGENT, "SIGNAL : %s", sig); + ret = GetBoolean(&coreDumped, buf, len, &begin); + } + + if (ret == WS_SUCCESS) { + WLOG(WS_LOG_AGENT, "Core Dumped?: %d", coreDumped); + sigSz = WOLFSSH_MAX_NAMESZ; + ret = GetString(sig, &sigSz, buf, len, &begin); + } + + if (ret == WS_SUCCESS) { + WLOG(WS_LOG_AGENT, "Error Msg : %s", sig); + sigSz = WOLFSSH_MAX_NAMESZ; + + /* getting language tag */ + ret = GetString(sig, &sigSz, buf, len, &begin); + } + } +#endif } if (ret == WS_SUCCESS) diff --git a/src/ssh.c b/src/ssh.c index 4597f8a03..de760c02b 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1365,6 +1365,19 @@ void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx) #endif +#if defined(WOLFSSH_TERM) || defined(WOLFSH_SHELL) +/* returns the exit status captured from the connection if any */ +int wolfSSH_GetExitStatus(WOLFSSH* ssh) +{ + if (ssh == NULL) { + WLOG(WS_LOG_DEBUG, "wolfSSH_GetExitStatus WOLFSSH struct was NULL"); + return WS_BAD_ARGUMENT; + } + return ssh->exitStatus; +} +#endif + + /* Used to set the channel request type sent in wolfSSH connect. The default * type set is shell if this function is not called. * diff --git a/wolfssh/internal.h b/wolfssh/internal.h index c31b229e7..054c1e194 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -822,6 +822,9 @@ struct WOLFSSH { byte* modes; word32 modesSz; #endif +#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) + word32 exitStatus; +#endif }; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 10da1f1c7..6e57aa675 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -293,6 +293,7 @@ typedef int (*WS_CallbackTerminalSize)(WOLFSSH*, word32, word32, word32, WOLFSSH_API void wolfSSH_SetTerminalResizeCb(WOLFSSH* ssh, WS_CallbackTerminalSize cb); WOLFSSH_API void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx); +WOLFSSH_API int wolfSSH_GetExitStatus(WOLFSSH* ssh); enum WS_HighwaterSide { From fda22526e2f492815f2cc4a539a785a5f884aac6 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 31 Oct 2023 14:42:09 -0600 Subject: [PATCH 02/35] add linux server side sending of exit-status --- apps/wolfsshd/wolfsshd.c | 12 ++++++++- src/internal.c | 58 ++++++++++++++++++++++++++++++++++++++++ src/ssh.c | 15 +++++++++++ wolfssh/internal.h | 2 ++ wolfssh/ssh.h | 1 + 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index b8b3673f7..551846219 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1308,7 +1308,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue opening shell"); exit(1); } - exit(0); /* exit child process and close down SSH connection */ + exit(ret); /* exit child process and close down SSH connection */ } /* do not wait for status of child process, and signal that the child can @@ -1454,6 +1454,16 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } + /* get return value of child process */ + { + int waitStatus; + waitpid(-1, &waitStatus, WNOHANG); + if (wolfSSH_SendExitStatus(ssh, (word32)WEXITSTATUS(waitStatus)) != + WS_SUCCESS) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue sending childs exit " + "status"); + } + } (void)conn; return WS_SUCCESS; } diff --git a/src/internal.c b/src/internal.c index 4e69277fb..ba11fc25e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14034,6 +14034,64 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success) } +/* Sends out the channel exit-status msg + * returns WS_SUCCESS on success */ +int SendChannelExitStatus(WOLFSSH* ssh, word32 channelId, word32 exitStatus) +{ + byte* output; + word32 idx; + int ret = WS_SUCCESS; + WOLFSSH_CHANNEL* channel = NULL; + const char cType[] = "exit-status"; + int typeSz; + + WLOG(WS_LOG_DEBUG, "Entering SendChannelExitStatus()"); + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; + + if (ret == WS_SUCCESS) { + channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF); + if (channel == NULL) { + WLOG(WS_LOG_DEBUG, "Invalid channel"); + ret = WS_INVALID_CHANID; + } + } + + if (ret == WS_SUCCESS) { + typeSz = (word32)WSTRLEN(cType); + ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ + + typeSz + BOOLEAN_SZ + UINT32_SZ); + } + + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; + + output[idx++] = MSGID_CHANNEL_REQUEST; + c32toa(channel->peerChannel, output + idx); + idx += UINT32_SZ; + + c32toa(typeSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, cType, typeSz); + idx += typeSz; + output[idx++] = 0; /* boolean of want reply is always false */ + c32toa(exitStatus, output + idx); + idx += UINT32_SZ; + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } + + if (ret == WS_SUCCESS) + ret = wolfSSH_SendPacket(ssh); + + WLOG(WS_LOG_DEBUG, "Leaving SendChannelExitStatus(), ret = %d", ret); + return ret; +} + + #if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \ !defined(NO_WOLFSSH_SERVER) /* cleans up absolute path diff --git a/src/ssh.c b/src/ssh.c index de760c02b..a7e8e9688 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1375,6 +1375,21 @@ int wolfSSH_GetExitStatus(WOLFSSH* ssh) } return ssh->exitStatus; } + + +/* Sends the commands exit status to the peer + * returns WS_SUCCESS on success */ +int wolfSSH_SendExitStatus(WOLFSSH* ssh, word32 exitStatus) +{ + if (ssh == NULL) { + WLOG(WS_LOG_DEBUG, "wolfSSH_SendExitStatus WOLFSSH struct was NULL"); + return WS_BAD_ARGUMENT; + } + WLOG(WS_LOG_DEBUG, "wolfSSH_SendExitStatus sending exit status %u", + exitStatus); + + return SendChannelExitStatus(ssh, ssh->defaultPeerChannelId, exitStatus); +} #endif diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 054c1e194..fe435b33e 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -956,6 +956,8 @@ WOLFSSH_LOCAL int SendChannelTerminalResize(WOLFSSH*, word32, word32, word32, WOLFSSH_LOCAL int SendChannelTerminalRequest(WOLFSSH* ssh); WOLFSSH_LOCAL int SendChannelAgentRequest(WOLFSSH* ssh); WOLFSSH_LOCAL int SendChannelSuccess(WOLFSSH*, word32, int); +WOLFSSH_LOCAL int SendChannelExitStatus(WOLFSSH* ssh, word32 channelId, + word32 exitStatus); WOLFSSH_LOCAL int GenerateKey(byte, byte, byte*, word32, const byte*, word32, const byte*, word32, const byte*, word32, byte doKeyPad); diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 6e57aa675..63c16574e 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -294,6 +294,7 @@ WOLFSSH_API void wolfSSH_SetTerminalResizeCb(WOLFSSH* ssh, WS_CallbackTerminalSize cb); WOLFSSH_API void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx); WOLFSSH_API int wolfSSH_GetExitStatus(WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_SendExitStatus(WOLFSSH* ssh, word32 exitStatus); enum WS_HighwaterSide { From f41e70682509ca134c62cb7bce10396c5d7522a8 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Wed, 1 Nov 2023 09:58:23 -0600 Subject: [PATCH 03/35] add exit status return to Windows server --- apps/wolfsshd/wolfsshd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 551846219..52805707d 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1140,6 +1140,12 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, HeapFree(GetProcessHeap(), 0, ext.lpAttributeList); } + if (wolfSSH_SendExitStatus(ssh, processState) != + WS_SUCCESS) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue sending childs exit " + "status"); + } + ClosePseudoConsole(pCon); CloseHandle(processInfo.hThread); CloseHandle(wolfSSHD_GetAuthToken(conn->auth)); From 0d480fa41992166ece602ae5b48c62b8c3918f3f Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 15:58:01 -0800 Subject: [PATCH 04/35] adjust shutdown for sending exit status cleanly --- apps/wolfsshd/wolfsshd.c | 10 ++++--- examples/client/client.c | 7 +++-- src/internal.c | 58 ---------------------------------------- src/ssh.c | 51 ++++++++++++++++++++++++----------- wolfssh/ssh.h | 2 +- 5 files changed, 48 insertions(+), 80 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 52805707d..bf9d91865 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1140,7 +1140,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, HeapFree(GetProcessHeap(), 0, ext.lpAttributeList); } - if (wolfSSH_SendExitStatus(ssh, processState) != + if (wolfSSH_SetExitStatus(ssh, processState) != WS_SUCCESS) { wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue sending childs exit " "status"); @@ -1464,7 +1464,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, { int waitStatus; waitpid(-1, &waitStatus, WNOHANG); - if (wolfSSH_SendExitStatus(ssh, (word32)WEXITSTATUS(waitStatus)) != + if (wolfSSH_SetExitStatus(ssh, (word32)WEXITSTATUS(waitStatus)) != WS_SUCCESS) { wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue sending childs exit " "status"); @@ -1722,9 +1722,12 @@ static void* HandleConnection(void* arg) break; } - if (error != WS_WANT_READ && error != WS_WANT_WRITE) { + if (ret == WS_FATAL_ERROR && + (error != WS_WANT_READ && + error != WS_WANT_WRITE)) { break; } + usleep(1); } if (attempt == maxAttempt) { @@ -1734,6 +1737,7 @@ static void* HandleConnection(void* arg) } } + /* check if there is a response to the shutdown */ wolfSSH_free(ssh); if (conn != NULL) { WCLOSESOCKET(conn->fd); diff --git a/examples/client/client.c b/examples/client/client.c index 25c3a5cd6..6c15fcbeb 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -982,7 +982,8 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) err_sys("Sending the shutdown messages failed."); } ret = wolfSSH_worker(ssh, NULL); - if (ret != WS_SUCCESS) { + if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E && + ret != WS_CHANNEL_CLOSED) { err_sys("Failed to listen for close messages from the peer."); } } @@ -994,8 +995,10 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) wolfSSH_free(ssh); wolfSSH_CTX_free(ctx); - if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E) + if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E && + ret != WS_CHANNEL_CLOSED) { err_sys("Closing client stream failed"); + } ClientFreeBuffers(pubKeyName, privKeyName); #if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) diff --git a/src/internal.c b/src/internal.c index ba11fc25e..4e69277fb 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14034,64 +14034,6 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success) } -/* Sends out the channel exit-status msg - * returns WS_SUCCESS on success */ -int SendChannelExitStatus(WOLFSSH* ssh, word32 channelId, word32 exitStatus) -{ - byte* output; - word32 idx; - int ret = WS_SUCCESS; - WOLFSSH_CHANNEL* channel = NULL; - const char cType[] = "exit-status"; - int typeSz; - - WLOG(WS_LOG_DEBUG, "Entering SendChannelExitStatus()"); - if (ssh == NULL) - ret = WS_BAD_ARGUMENT; - - if (ret == WS_SUCCESS) { - channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF); - if (channel == NULL) { - WLOG(WS_LOG_DEBUG, "Invalid channel"); - ret = WS_INVALID_CHANID; - } - } - - if (ret == WS_SUCCESS) { - typeSz = (word32)WSTRLEN(cType); - ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ + - typeSz + BOOLEAN_SZ + UINT32_SZ); - } - - if (ret == WS_SUCCESS) { - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; - - output[idx++] = MSGID_CHANNEL_REQUEST; - c32toa(channel->peerChannel, output + idx); - idx += UINT32_SZ; - - c32toa(typeSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, cType, typeSz); - idx += typeSz; - output[idx++] = 0; /* boolean of want reply is always false */ - c32toa(exitStatus, output + idx); - idx += UINT32_SZ; - - ssh->outputBuffer.length = idx; - - ret = BundlePacket(ssh); - } - - if (ret == WS_SUCCESS) - ret = wolfSSH_SendPacket(ssh); - - WLOG(WS_LOG_DEBUG, "Leaving SendChannelExitStatus(), ret = %d", ret); - return ret; -} - - #if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \ !defined(NO_WOLFSSH_SERVER) /* cleans up absolute path diff --git a/src/ssh.c b/src/ssh.c index a7e8e9688..d5b53af07 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -954,24 +954,43 @@ int wolfSSH_connect(WOLFSSH* ssh) int wolfSSH_shutdown(WOLFSSH* ssh) { int ret = WS_SUCCESS; + WOLFSSH_CHANNEL* channel = NULL; WLOG(WS_LOG_DEBUG, "Entering wolfSSH_shutdown()"); if (ssh == NULL || ssh->channelList == NULL) ret = WS_BAD_ARGUMENT; - if (ret == WS_SUCCESS) - ret = SendChannelEof(ssh, ssh->channelList->peerChannel); + /* look up the channel if it still exists */ + if (ret == WS_SUCCESS) { + channel = ChannelFind(ssh, ssh->channelList->peerChannel, WS_CHANNEL_ID_SELF); + } - /* continue on success and in case where queing up send packets */ - if (ret == WS_SUCCESS || - (ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE)) - ret = SendChannelExit(ssh, ssh->channelList->peerChannel, 0); + /* if channel close was not already sent then send it */ + if (channel != NULL && !channel->closeTxd) { + if (ret == WS_SUCCESS) { + ret = SendChannelEof(ssh, ssh->channelList->peerChannel); + } - /* continue on success and in case where queing up send packets */ - if (ret == WS_SUCCESS || - (ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE)) - ret = SendChannelClose(ssh, ssh->channelList->peerChannel); + /* continue on success and in case where queing up send packets */ + if (ret == WS_SUCCESS || + (ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE)) { + ret = SendChannelExit(ssh, ssh->channelList->peerChannel, + ssh->exitStatus); + } + + /* continue on success and in case where queing up send packets */ + if (ret == WS_SUCCESS || + (ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE)) + ret = SendChannelClose(ssh, ssh->channelList->peerChannel); + } + + + /* if the channel was not yet removed then read to get + * response to SendChannelClose */ + if (channel != NULL && ret == WS_SUCCESS) { + ret = wolfSSH_worker(ssh, NULL); + } if (ssh != NULL && ssh->channelList == NULL) { WLOG(WS_LOG_DEBUG, "channel list was already removed"); @@ -1377,18 +1396,18 @@ int wolfSSH_GetExitStatus(WOLFSSH* ssh) } -/* Sends the commands exit status to the peer +/* Sets the exit status to send on shutdown * returns WS_SUCCESS on success */ -int wolfSSH_SendExitStatus(WOLFSSH* ssh, word32 exitStatus) +int wolfSSH_SetExitStatus(WOLFSSH* ssh, word32 exitStatus) { if (ssh == NULL) { - WLOG(WS_LOG_DEBUG, "wolfSSH_SendExitStatus WOLFSSH struct was NULL"); + WLOG(WS_LOG_DEBUG, "wolfSSH_SetExitStatus WOLFSSH struct was NULL"); return WS_BAD_ARGUMENT; } - WLOG(WS_LOG_DEBUG, "wolfSSH_SendExitStatus sending exit status %u", + WLOG(WS_LOG_DEBUG, "wolfSSH_SetExitStatus sending exit status %u", exitStatus); - - return SendChannelExitStatus(ssh, ssh->defaultPeerChannelId, exitStatus); + ssh->exitStatus = exitStatus; + return WS_SUCCESS; } #endif diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 63c16574e..0e2d49f85 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -294,7 +294,7 @@ WOLFSSH_API void wolfSSH_SetTerminalResizeCb(WOLFSSH* ssh, WS_CallbackTerminalSize cb); WOLFSSH_API void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx); WOLFSSH_API int wolfSSH_GetExitStatus(WOLFSSH* ssh); -WOLFSSH_API int wolfSSH_SendExitStatus(WOLFSSH* ssh, word32 exitStatus); +WOLFSSH_API int wolfSSH_SetExitStatus(WOLFSSH* ssh, word32 exitStatus); enum WS_HighwaterSide { From 6791f979aa1c17708e2a8b07f1350eef066c6870 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 16:09:25 -0800 Subject: [PATCH 05/35] account for sleep on windows --- apps/wolfsshd/wolfsshd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index bf9d91865..923044fb1 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1727,7 +1727,11 @@ static void* HandleConnection(void* arg) error != WS_WANT_WRITE)) { break; } - usleep(1); + #ifdef _WIN32 + Sleep(1); + #else + usleep(1); + #endif } if (attempt == maxAttempt) { From 3efdeaa037f69d0a1d7e8abace4cec9473a3bc63 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 16:14:10 -0800 Subject: [PATCH 06/35] fix build with disable term --- src/ssh.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ssh.c b/src/ssh.c index d5b53af07..b38852981 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -976,7 +976,11 @@ int wolfSSH_shutdown(WOLFSSH* ssh) if (ret == WS_SUCCESS || (ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE)) { ret = SendChannelExit(ssh, ssh->channelList->peerChannel, + #if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) ssh->exitStatus); + #else + 0); + #endif } /* continue on success and in case where queing up send packets */ From 9b5c54cd7f991119c01d673397ef8980f7c0c5eb Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 20:16:36 -0800 Subject: [PATCH 07/35] account for small highwater mark test case --- tests/api.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/api.c b/tests/api.c index c417a1c56..b7f26063a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1051,6 +1051,14 @@ static void test_wolfSSH_SFTP_SendReadPacket(void) /* If the socket is closed on shutdown, peer is gone, this is OK. */ argsCount = WS_SUCCESS; } + +#if DEFAULT_HIGHWATER_MARK < 8000 + if (argsCount == WS_REKEYING) { + /* in cases where highwater mark is really small a re-key could happen */ + argsCount = WS_SUCCESS; + } +#endif + AssertIntEQ(argsCount, WS_SUCCESS); wolfSSH_free(ssh); From 11329a4b625107d0fb87285dd576de6f0ae2507e Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 20:28:24 -0800 Subject: [PATCH 08/35] add error return test case --- apps/wolfsshd/test/error_return.sh | 30 ++++++++++++++++++++++++ apps/wolfsshd/test/run_all_sshd_tests.sh | 1 + 2 files changed, 31 insertions(+) create mode 100755 apps/wolfsshd/test/error_return.sh diff --git a/apps/wolfsshd/test/error_return.sh b/apps/wolfsshd/test/error_return.sh new file mode 100755 index 000000000..25d2a581b --- /dev/null +++ b/apps/wolfsshd/test/error_return.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# sshd local test + +PWD=`pwd` +cd ../../.. + +TEST_CLIENT="./examples/client/client" +USER=`whoami` +PRIVATE_KEY="./keys/hansel-key-ecc.der" +PUBLIC_KEY="./keys/hansel-key-ecc.pub" + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "expecting host and port as arguments" + echo "./error_return.sh 127.0.0.1 22222" + exit -1 +fi + +echo "$TEST_CLIENT -c 'ls error' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h \"$1\" -p \"$2\"" +$TEST_CLIENT -c 'ls error' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h "$1" -p "$2" +if [ $? != 2 ]; then + echo "Expecting error return value of 2 for failed ls command" + cd $PWD + exit 1 +fi + +cd $PWD +exit 0 + + diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 4c082d2cd..7e03e61bf 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -52,6 +52,7 @@ run_test() { run_test "sshd_exec_test.sh" run_test "sshd_term_size_test.sh" +run_test "error_return.sh" # add aditional tests here, check on var USING_LOCAL_HOST if can make sshd # server start/restart with changes From 965a0c5b463f47567eace1c22dd1c1eb1c75207f Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 8 Dec 2023 10:41:22 -0700 Subject: [PATCH 09/35] add debug for test case --- apps/wolfsshd/test/error_return.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/wolfsshd/test/error_return.sh b/apps/wolfsshd/test/error_return.sh index 25d2a581b..63e88a158 100755 --- a/apps/wolfsshd/test/error_return.sh +++ b/apps/wolfsshd/test/error_return.sh @@ -18,8 +18,9 @@ fi echo "$TEST_CLIENT -c 'ls error' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h \"$1\" -p \"$2\"" $TEST_CLIENT -c 'ls error' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h "$1" -p "$2" -if [ $? != 2 ]; then - echo "Expecting error return value of 2 for failed ls command" +RESULT=$? +if [ "$RESULT" != 2 ]; then + echo "Expecting error return value of 2 for failed ls command, found $RESULT" cd $PWD exit 1 fi From 8fe719c373c13a02d4f2ecd339225844934732da Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 8 Dec 2023 10:46:03 -0700 Subject: [PATCH 10/35] disable test case until resolving for use with github actions --- apps/wolfsshd/test/run_all_sshd_tests.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 7e03e61bf..017609c5e 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -52,7 +52,10 @@ run_test() { run_test "sshd_exec_test.sh" run_test "sshd_term_size_test.sh" -run_test "error_return.sh" + +#Github actions needs resolved for these test cases +#run_test "error_return.sh" +#run_test "sshd_login_grace_test.sh" # add aditional tests here, check on var USING_LOCAL_HOST if can make sshd # server start/restart with changes From 7d2b4c5e393d48ba98686c1ecfea7a94cce54768 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 22 Jan 2024 15:10:53 -0700 Subject: [PATCH 11/35] fix typo in macro guard --- apps/wolfssh/wolfssh.c | 2 +- apps/wolfsshd/wolfsshd.c | 2 +- examples/client/client.c | 2 +- src/ssh.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/wolfssh/wolfssh.c b/apps/wolfssh/wolfssh.c index 0b6e1ba03..21242d7b2 100644 --- a/apps/wolfssh/wolfssh.c +++ b/apps/wolfssh/wolfssh.c @@ -1105,7 +1105,7 @@ static THREAD_RETURN WOLFSSH_THREAD wolfSSH_Client(void* args) } WCLOSESOCKET(sockFd); -#if defined(WOLFSSH_TERM) || defined(WOLFSH_SHELL) +#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) ((func_args*)args)->return_code = wolfSSH_GetExitStatus(ssh); #endif diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 923044fb1..35096f824 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1667,7 +1667,7 @@ static void* HandleConnection(void* arg) SHELL_Subsystem(conn, ssh, pPasswd, usrConf, wolfSSH_GetSessionCommand(ssh)); } - #endif /* WOLFSH_SHELL */ + #endif /* WOLFSSH_SHELL */ /* SCP can be an exec type */ if (ret == WS_SCP_INIT) { diff --git a/examples/client/client.c b/examples/client/client.c index 6c15fcbeb..4d56575f6 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -989,7 +989,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) } WCLOSESOCKET(sockFd); -#if defined(WOLFSSH_TERM) || defined(WOLFSH_SHELL) +#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) ((func_args*)args)->return_code = wolfSSH_GetExitStatus(ssh); #endif diff --git a/src/ssh.c b/src/ssh.c index b38852981..c0b70ab66 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1388,7 +1388,7 @@ void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx) #endif -#if defined(WOLFSSH_TERM) || defined(WOLFSH_SHELL) +#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) /* returns the exit status captured from the connection if any */ int wolfSSH_GetExitStatus(WOLFSSH* ssh) { From 6e5a614260539a71834af93be3394ec02bdb691d Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 22 Jan 2024 15:28:12 -0700 Subject: [PATCH 12/35] update return code test case --- apps/wolfsshd/test/error_return.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/wolfsshd/test/error_return.sh b/apps/wolfsshd/test/error_return.sh index 63e88a158..0c00336e5 100755 --- a/apps/wolfsshd/test/error_return.sh +++ b/apps/wolfsshd/test/error_return.sh @@ -16,8 +16,8 @@ if [ -z "$1" ] || [ -z "$2" ]; then exit -1 fi -echo "$TEST_CLIENT -c 'ls error' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h \"$1\" -p \"$2\"" -$TEST_CLIENT -c 'ls error' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h "$1" -p "$2" +echo "$TEST_CLIENT -c 'bash -c \"(exit 2)\"' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h \"$1\" -p \"$2\"" +$TEST_CLIENT -c 'bash -c "(exit 2)"' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h "$1" -p "$2" RESULT=$? if [ "$RESULT" != 2 ]; then echo "Expecting error return value of 2 for failed ls command, found $RESULT" From 39b6e26c7e716fbd36217b62c31ff9ecbaf5ec95 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 23 Jan 2024 14:39:47 -0700 Subject: [PATCH 13/35] improve unix/linux wait for child exit status --- apps/wolfsshd/wolfsshd.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 35096f824..ae2947e32 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1463,11 +1463,22 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, /* get return value of child process */ { int waitStatus; - waitpid(-1, &waitStatus, WNOHANG); - if (wolfSSH_SetExitStatus(ssh, (word32)WEXITSTATUS(waitStatus)) != + + do { + rc = waitpid(childPid, &waitStatus, 0); + /* if the waitpid experinced an interupt then try again */ + } while (rc < 0 && errno == EINTR); + + if (rc < 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue waiting for childs exit " + "status"); + } + else { + if (wolfSSH_SetExitStatus(ssh, (word32)WEXITSTATUS(waitStatus)) != WS_SUCCESS) { - wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue sending childs exit " - "status"); + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue setting childs exit " + "status"); + } } } (void)conn; From ad8bd954a18bd4cd8ae5c330d4e11a5d3b4a0e74 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 23 Jan 2024 14:44:20 -0700 Subject: [PATCH 14/35] do not set SIG_IGN now that the parent process is getting the childs exit status --- apps/wolfsshd/wolfsshd.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index ae2947e32..1a7f8341d 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1317,10 +1317,6 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, exit(ret); /* exit child process and close down SSH connection */ } - /* do not wait for status of child process, and signal that the child can - * be reaped to avoid zombie processes when running in the foreground */ - signal(SIGCHLD, SIG_IGN); - if (wolfSSHD_AuthReducePermissionsUser(conn->auth, pPasswd->pw_uid, pPasswd->pw_gid) != WS_SUCCESS) { wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user ID"); From b711d6223858644fe6f36e8e4ca2dd8607bd5bad Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 22:39:02 -0800 Subject: [PATCH 15/35] add piping of stderr --- apps/wolfsshd/auth.c | 4 ++ apps/wolfsshd/wolfsshd.c | 79 ++++++++++++++++++++++++++-- src/internal.c | 109 +++++++++++++++++++++++++++++++++++++++ src/ssh.c | 21 ++++++++ wolfssh/internal.h | 1 + wolfssh/ssh.h | 1 + 6 files changed, 210 insertions(+), 5 deletions(-) diff --git a/apps/wolfsshd/auth.c b/apps/wolfsshd/auth.c index bcb8c6304..4be651626 100644 --- a/apps/wolfsshd/auth.c +++ b/apps/wolfsshd/auth.c @@ -380,6 +380,8 @@ static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz, WOLFS if (pwInfo == NULL) { /* user name not found on system */ ret = WS_FATAL_ERROR; + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] User name not found on system"); } } @@ -412,6 +414,8 @@ static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz, WOLFS if (ret == WS_SUCCESS) { storedHashCpy = WSTRDUP(storedHash, NULL, DYNTYPE_STRING); if (storedHash == NULL) { + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] Error getting stored hash copy"); ret = WS_MEMORY_E; } } diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index bd3ad8ed4..b2bea0ab4 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1167,6 +1167,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, WS_SOCKET_T sshFd = 0; int rc; WS_SOCKET_T childFd = 0; + int stdoutPipe[2], stderrPipe[2]; pid_t childPid; #ifndef EXAMPLE_BUFFER_SZ @@ -1198,6 +1199,18 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, return WS_FATAL_ERROR; } + /* create pipes for stdout and stderr */ + if (pipe(stdoutPipe) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stdout pipe"); + return WS_FATAL_ERROR; + } + if (pipe(stderrPipe) != 0) { + close(stdoutPipe[0]); + close(stderrPipe[1]); + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stderr pipe"); + return WS_FATAL_ERROR; + } + ChildRunning = 1; childPid = forkpty(&childFd, NULL, NULL, NULL); if (childPid < 0) { @@ -1216,6 +1229,27 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, signal(SIGINT, SIG_DFL); signal(SIGCHLD, SIG_DFL); + close(stdoutPipe[0]); + close(stderrPipe[0]); + if (dup2(stdoutPipe[1], STDOUT_FILENO) == -1) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error redirecting stdout pipe"); + if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) { + /* stop everything if not able to reduce permissions level */ + exit(1); + } + + return WS_FATAL_ERROR; + } + if (dup2(stderrPipe[1], STDERR_FILENO) == -1) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error redirecting stderr pipe"); + if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) { + /* stop everything if not able to reduce permissions level */ + exit(1); + } + + return WS_FATAL_ERROR; + } + /* set additional groups if needed */ if (wolfSSHD_AuthSetGroups(conn->auth, wolfSSH_GetUsername(ssh), pPasswd->pw_gid) != WS_SUCCESS) { @@ -1310,6 +1344,8 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, else { ret = execv(cmd, (char**)args); } + close(stdoutPipe[1]); + close(stderrPipe[1]); if (ret && errno) { wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue opening shell"); exit(1); @@ -1359,6 +1395,8 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, #endif wolfSSH_SetTerminalResizeCtx(ssh, (void*)&childFd); + close(stdoutPipe[1]); + close(stderrPipe[1]); while (ChildRunning) { byte tmp[2]; @@ -1372,9 +1410,14 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, FD_SET(sshFd, &readFds); maxFd = sshFd; - FD_SET(childFd, &readFds); - if (childFd > maxFd) - maxFd = childFd; + /* select on stdout/stderr pipes */ + FD_SET(stdoutPipe[0], &readFds); + if (stdoutPipe[0] > maxFd) + maxFd = stdoutPipe[0]; + + FD_SET(stderrPipe[0], &readFds); + if (stderrPipe[0] > maxFd) + maxFd = stderrPipe[0]; if (wolfSSH_stream_peek(ssh, tmp, 1) <= 0) { rc = select((int)maxFd + 1, &readFds, NULL, NULL, NULL); @@ -1432,8 +1475,31 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } - if (FD_ISSET(childFd, &readFds)) { - cnt_r = (int)read(childFd, shellBuffer, sizeof shellBuffer); + if (FD_ISSET(stderrPipe[0], &readFds)) { + cnt_r = (int)read(stderrPipe[0], shellBuffer, sizeof shellBuffer); + /* This read will return 0 on EOF */ + if (cnt_r <= 0) { + int err = errno; + if (err != EAGAIN) { + break; + } + } + else { + if (cnt_r > 0) { + cnt_w = wolfSSH_extended_data_send(ssh, shellBuffer, cnt_r); + if (cnt_w == WS_WINDOW_FULL) { + windowFull = 1; + continue; + } + else if (cnt_w < 0) + break; + } + } + } + + /* handle stdout */ + if (FD_ISSET(stdoutPipe[0], &readFds)) { + cnt_r = (int)read(stdoutPipe[0], shellBuffer, sizeof shellBuffer); /* This read will return 0 on EOF */ if (cnt_r <= 0) { int err = errno; @@ -1477,6 +1543,9 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } } + close(stdoutPipe[0]); + close(stderrPipe[0]); + (void)conn; return WS_SUCCESS; } diff --git a/src/internal.c b/src/internal.c index 4e69277fb..1da411cc5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -13428,6 +13428,115 @@ int SendChannelData(WOLFSSH* ssh, word32 channelId, } +int SendChannelExtendedData(WOLFSSH* ssh, word32 channelId, + byte* data, word32 dataSz) +{ + byte* output; + word32 idx; + int ret = WS_SUCCESS; + WOLFSSH_CHANNEL* channel = NULL; + + WLOG(WS_LOG_DEBUG, "Entering SendChannelData()"); + + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; + + if (ret == WS_SUCCESS) { + if (ssh->isKeying) + ret = WS_REKEYING; + } + + /* if already having data pending try to flush it first and do not continue + * to que more on fail */ + if (ret == WS_SUCCESS && ssh->outputBuffer.plainSz > 0) { + WLOG(WS_LOG_DEBUG, "Flushing out want write data"); + ret = wolfSSH_SendPacket(ssh); + if (ret != WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "Leaving SendChannelData(), ret = %d", ret); + return ret; + } + + } + + if (ret == WS_SUCCESS) { + if (ssh->outputBuffer.length != 0) + ret = wolfSSH_SendPacket(ssh); + } + + if (ret == WS_SUCCESS) { + channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF); + if (channel == NULL) { + WLOG(WS_LOG_DEBUG, "Invalid channel"); + ret = WS_INVALID_CHANID; + } + } + + if (ret == WS_SUCCESS) { + if (channel->peerWindowSz == 0) { + WLOG(WS_LOG_DEBUG, "channel window is full"); + ssh->error = WS_WINDOW_FULL; + ret = WS_WINDOW_FULL; + } + } + + if (ret == WS_SUCCESS) { + word32 bound = min(channel->peerWindowSz, channel->peerMaxPacketSz); + bound = min(bound, channel->maxPacketSz); + + if (dataSz > bound) { + WLOG(WS_LOG_DEBUG, + "Trying to send %u, client will only accept %u, limiting", + dataSz, bound); + dataSz = bound; + } + + ret = PreparePacket(ssh, + MSG_ID_SZ + UINT32_SZ + UINT32_SZ + LENGTH_SZ + dataSz); + } + + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; + + + output[idx++] = MSGID_CHANNEL_EXTENDED_DATA; + c32toa(channel->peerChannel, output + idx); + idx += UINT32_SZ; + c32toa(CHANNEL_EXTENDED_DATA_STDERR, output + idx); + idx += UINT32_SZ; + c32toa(dataSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, data, dataSz); + idx += dataSz; + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } + + if (ret == WS_SUCCESS) { + WLOG(WS_LOG_INFO, " dataSz = %u", dataSz); + WLOG(WS_LOG_INFO, " peerWindowSz = %u", channel->peerWindowSz); + channel->peerWindowSz -= dataSz; + WLOG(WS_LOG_INFO, " update peerWindowSz = %u", channel->peerWindowSz); + } + + /* at this point the data has been loaded into WOLFSSH structure and is + * considered consumed */ + if (ret == WS_SUCCESS) + ret = wolfSSH_SendPacket(ssh); + + if (ret == WS_SUCCESS || ret == WS_WANT_WRITE) + ret = dataSz; + + if (ssh && ssh->error == WS_WANT_WRITE) + ssh->outputBuffer.plainSz = dataSz; + + WLOG(WS_LOG_DEBUG, "Leaving SendChannelExtendedData(), ret = %d", ret); + return ret; +} + + int SendChannelWindowAdjust(WOLFSSH* ssh, word32 channelId, word32 bytesToAdd) { diff --git a/src/ssh.c b/src/ssh.c index c0b70ab66..73a48231a 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1222,6 +1222,27 @@ int wolfSSH_global_request(WOLFSSH *ssh, const unsigned char* data, word32 dataS } +int wolfSSH_extended_data_send(WOLFSSH* ssh, byte* buf, word32 bufSz) +{ + int bytesTxd = 0; + + WLOG(WS_LOG_DEBUG, "Entering wolfSSH_extended_data_send()"); + + if (ssh == NULL || buf == NULL || ssh->channelList == NULL) + return WS_BAD_ARGUMENT; + + if (ssh->isKeying) { + ssh->error = WS_REKEYING; + return WS_REKEYING; + } + + bytesTxd = SendChannelExtendedData(ssh, ssh->channelList->channel, buf, bufSz); + + WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_extended_data_send(), txd = %d", bytesTxd); + return bytesTxd; +} + + /* Reads pending data from extended data buffer. Currently can be used to get * STDERR information sent across the channel. * Returns the number of bytes read on success */ diff --git a/wolfssh/internal.h b/wolfssh/internal.h index fe435b33e..631edf107 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -949,6 +949,7 @@ WOLFSSH_LOCAL int SendChannelEow(WOLFSSH*, word32); WOLFSSH_LOCAL int SendChannelClose(WOLFSSH*, word32); WOLFSSH_LOCAL int SendChannelExit(WOLFSSH*, word32, int); WOLFSSH_LOCAL int SendChannelData(WOLFSSH*, word32, byte*, word32); +WOLFSSH_LOCAL int SendChannelExtendedData(WOLFSSH*, word32, byte*, word32); WOLFSSH_LOCAL int SendChannelWindowAdjust(WOLFSSH*, word32, word32); WOLFSSH_LOCAL int SendChannelRequest(WOLFSSH*, byte*, word32); WOLFSSH_LOCAL int SendChannelTerminalResize(WOLFSSH*, word32, word32, word32, diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 0e2d49f85..218a44484 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -256,6 +256,7 @@ WOLFSSH_API int wolfSSH_stream_peek(WOLFSSH*, byte*, word32); WOLFSSH_API int wolfSSH_stream_read(WOLFSSH*, byte*, word32); WOLFSSH_API int wolfSSH_stream_send(WOLFSSH*, byte*, word32); WOLFSSH_API int wolfSSH_stream_exit(WOLFSSH*, int); +WOLFSSH_API int wolfSSH_extended_data_send(WOLFSSH* ssh, byte* buf, word32 bufSz); WOLFSSH_API int wolfSSH_extended_data_read(WOLFSSH*, byte*, word32); WOLFSSH_API int wolfSSH_TriggerKeyExchange(WOLFSSH*); WOLFSSH_API int wolfSSH_SendIgnore(WOLFSSH*, const byte*, word32); From fee6f31ab66b69211c32a63a850446a5d574f4de Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sun, 5 Nov 2023 22:40:32 -0800 Subject: [PATCH 16/35] add option to generate user certs --- keys/renewcerts.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/keys/renewcerts.sh b/keys/renewcerts.sh index 2aadb7144..5c630bdfe 100755 --- a/keys/renewcerts.sh +++ b/keys/renewcerts.sh @@ -1,14 +1,23 @@ touch index.txt +if [ -z "$1" ]; then + USER_NAME="fred" +else + USER_NAME=$1 + cp fred-key.der $USER_NAME-key.der + cp fred-key.pem $USER_NAME-key.pem + sed -i "s/fred/$USER_NAME/g" renewcerts.cnf +fi + # renew CA openssl req -subj '/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=ca@example.com' -key ca-key-ecc.pem -text -out ca-cert-ecc.pem -config renewcerts.cnf -new -nodes -x509 -extensions v3_ca -days 3650 -set_serial 6 openssl x509 -in ca-cert-ecc.pem -outform DER -out ca-cert-ecc.der -# renew fred-cert -openssl req -subj '/C=US/ST=WA/L=Seattle/O=wolfSSL Inc/OU=Development/CN=Fred/emailAddress=fred@example.com' -key fred-key.pem -out fred-cert.csr -config renewcerts.cnf -new -nodes +# renew user cert +openssl req -subj "/C=US/ST=WA/L=Seattle/O=wolfSSL Inc/OU=Development/CN=$USER_NAME/emailAddress=fred@example.com" -key $USER_NAME-key.pem -out $USER_NAME-cert.csr -config renewcerts.cnf -new -nodes -openssl x509 -req -in fred-cert.csr -days 3650 -extfile renewcerts.cnf -extensions v3_fred -CA ca-cert-ecc.pem -CAkey ca-key-ecc.pem -text -out fred-cert.pem -set_serial 7 -openssl x509 -in fred-cert.pem -outform DER -out fred-cert.der +openssl x509 -req -in $USER_NAME-cert.csr -days 3650 -extfile renewcerts.cnf -extensions v3_$USER_NAME -CA ca-cert-ecc.pem -CAkey ca-key-ecc.pem -text -out $USER_NAME-cert.pem -set_serial 7 +openssl x509 -in $USER_NAME-cert.pem -outform DER -out $USER_NAME-cert.der # renew server-cert openssl req -subj '/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC/CN=www.wolfssl.com/emailAddress=server@example.com' -key server-key.pem -out server-cert.csr -config renewcerts.cnf -new -nodes From e8f34afe6e4573ee1b4fc4045d4926245d7853d5 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 6 Nov 2023 23:33:52 -0800 Subject: [PATCH 17/35] fix to only use stdout/stderr pipes with forced commands --- apps/wolfsshd/wolfsshd.c | 188 ++++++++++++++++++++++++--------------- 1 file changed, 116 insertions(+), 72 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index b2bea0ab4..c63ef5c21 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1200,15 +1200,17 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } /* create pipes for stdout and stderr */ - if (pipe(stdoutPipe) != 0) { - wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stdout pipe"); - return WS_FATAL_ERROR; - } - if (pipe(stderrPipe) != 0) { - close(stdoutPipe[0]); - close(stderrPipe[1]); - wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stderr pipe"); - return WS_FATAL_ERROR; + if (forcedCmd) { + if (pipe(stdoutPipe) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stdout pipe"); + return WS_FATAL_ERROR; + } + if (pipe(stderrPipe) != 0) { + close(stdoutPipe[0]); + close(stderrPipe[1]); + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stderr pipe"); + return WS_FATAL_ERROR; + } } ChildRunning = 1; @@ -1229,25 +1231,27 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, signal(SIGINT, SIG_DFL); signal(SIGCHLD, SIG_DFL); - close(stdoutPipe[0]); - close(stderrPipe[0]); - if (dup2(stdoutPipe[1], STDOUT_FILENO) == -1) { - wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error redirecting stdout pipe"); - if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) { - /* stop everything if not able to reduce permissions level */ - exit(1); - } + if (forcedCmd) { + close(stdoutPipe[0]); + close(stderrPipe[0]); + if (dup2(stdoutPipe[1], STDOUT_FILENO) == -1) { + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] Error redirecting stdout pipe"); + if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) { + exit(1); + } - return WS_FATAL_ERROR; - } - if (dup2(stderrPipe[1], STDERR_FILENO) == -1) { - wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error redirecting stderr pipe"); - if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) { - /* stop everything if not able to reduce permissions level */ - exit(1); + return WS_FATAL_ERROR; } + if (dup2(stderrPipe[1], STDERR_FILENO) == -1) { + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] Error redirecting stderr pipe"); + if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) { + exit(1); + } - return WS_FATAL_ERROR; + return WS_FATAL_ERROR; + } } /* set additional groups if needed */ @@ -1340,12 +1344,12 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, args[1] = "-c"; args[2] = forcedCmd; ret = execv(cmd, (char**)args); + close(stdoutPipe[1]); + close(stderrPipe[1]); } else { ret = execv(cmd, (char**)args); } - close(stdoutPipe[1]); - close(stderrPipe[1]); if (ret && errno) { wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue opening shell"); exit(1); @@ -1395,8 +1399,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, #endif wolfSSH_SetTerminalResizeCtx(ssh, (void*)&childFd); - close(stdoutPipe[1]); - close(stderrPipe[1]); + if (forcedCmd) { + close(stdoutPipe[1]); + close(stderrPipe[1]); + } while (ChildRunning) { byte tmp[2]; @@ -1410,14 +1416,21 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, FD_SET(sshFd, &readFds); maxFd = sshFd; - /* select on stdout/stderr pipes */ - FD_SET(stdoutPipe[0], &readFds); - if (stdoutPipe[0] > maxFd) - maxFd = stdoutPipe[0]; + /* select on stdout/stderr pipes with forced commands */ + if (forcedCmd) { + FD_SET(stdoutPipe[0], &readFds); + if (stdoutPipe[0] > maxFd) + maxFd = stdoutPipe[0]; - FD_SET(stderrPipe[0], &readFds); - if (stderrPipe[0] > maxFd) - maxFd = stderrPipe[0]; + FD_SET(stderrPipe[0], &readFds); + if (stderrPipe[0] > maxFd) + maxFd = stderrPipe[0]; + } + else { + FD_SET(childFd, &readFds); + if (childFd > maxFd) + maxFd = childFd; + } if (wolfSSH_stream_peek(ssh, tmp, 1) <= 0) { rc = select((int)maxFd + 1, &readFds, NULL, NULL, NULL); @@ -1475,48 +1488,77 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } - if (FD_ISSET(stderrPipe[0], &readFds)) { - cnt_r = (int)read(stderrPipe[0], shellBuffer, sizeof shellBuffer); - /* This read will return 0 on EOF */ - if (cnt_r <= 0) { - int err = errno; - if (err != EAGAIN) { - break; + if (forcedCmd) { + if (FD_ISSET(stderrPipe[0], &readFds)) { + cnt_r = (int)read(stderrPipe[0], shellBuffer, + sizeof shellBuffer); + /* This read will return 0 on EOF */ + if (cnt_r <= 0) { + int err = errno; + if (err != EAGAIN) { + break; + } } - } - else { - if (cnt_r > 0) { - cnt_w = wolfSSH_extended_data_send(ssh, shellBuffer, cnt_r); - if (cnt_w == WS_WINDOW_FULL) { - windowFull = 1; - continue; + else { + if (cnt_r > 0) { + cnt_w = wolfSSH_extended_data_send(ssh, shellBuffer, + cnt_r); + if (cnt_w == WS_WINDOW_FULL) { + windowFull = 1; + continue; + } + else if (cnt_w < 0) + break; } - else if (cnt_w < 0) - break; } } - } - /* handle stdout */ - if (FD_ISSET(stdoutPipe[0], &readFds)) { - cnt_r = (int)read(stdoutPipe[0], shellBuffer, sizeof shellBuffer); - /* This read will return 0 on EOF */ - if (cnt_r <= 0) { - int err = errno; - if (err != EAGAIN) { - break; + /* handle stdout */ + if (FD_ISSET(stdoutPipe[0], &readFds)) { + cnt_r = (int)read(stdoutPipe[0], shellBuffer, + sizeof shellBuffer); + /* This read will return 0 on EOF */ + if (cnt_r <= 0) { + int err = errno; + if (err != EAGAIN) { + break; + } } - } - else { - if (cnt_r > 0) { - cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, - shellBuffer, cnt_r); - if (cnt_w == WS_WINDOW_FULL) { - windowFull = 1; - continue; + else { + if (cnt_r > 0) { + cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, + shellBuffer, cnt_r); + if (cnt_w == WS_WINDOW_FULL) { + windowFull = 1; + continue; + } + else if (cnt_w < 0) + break; } - else if (cnt_w < 0) + } + } + } + else { + if (FD_ISSET(childFd, &readFds)) { + cnt_r = (int)read(childFd, shellBuffer, sizeof shellBuffer); + /* This read will return 0 on EOF */ + if (cnt_r <= 0) { + int err = errno; + if (err != EAGAIN) { break; + } + } + else { + if (cnt_r > 0) { + cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, + shellBuffer, cnt_r); + if (cnt_w == WS_WINDOW_FULL) { + windowFull = 1; + continue; + } + else if (cnt_w < 0) + break; + } } } } @@ -1543,8 +1585,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } } - close(stdoutPipe[0]); - close(stderrPipe[0]); + if (forcedCmd) { + close(stdoutPipe[0]); + close(stderrPipe[0]); + } (void)conn; return WS_SUCCESS; From 0a24dccd7f7c7a313bff26ea393071a45049525a Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 7 Nov 2023 00:29:19 -0800 Subject: [PATCH 18/35] add additional x509 connection test --- apps/wolfsshd/test/create_sshd_config.sh | 10 +++++++--- apps/wolfsshd/test/run_all_sshd_tests.sh | 19 +++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/apps/wolfsshd/test/create_sshd_config.sh b/apps/wolfsshd/test/create_sshd_config.sh index 3069a2eda..19be76acd 100755 --- a/apps/wolfsshd/test/create_sshd_config.sh +++ b/apps/wolfsshd/test/create_sshd_config.sh @@ -26,11 +26,15 @@ PermitEmptyPasswords no UsePrivilegeSeparation no UseDNS no -TrustedUserCAKeys $PWD/ca-cert-ecc.pem -HostKey $PWD/server-key.pem -HostCertificate $PWD/server-cert.pem +TrustedUserCAKeys $PWD/../../../keys/ca-cert-ecc.pem +HostKey $PWD/../../../keys/server-key.pem +HostCertificate $PWD/../../../keys/server-cert.pem EOF +cd ../../../keys/ +./renewcerts.sh $1 +cd ../apps/wolfsshd/test/ + exit 0 diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 017609c5e..aac061746 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -2,15 +2,16 @@ echo "Running all wolfSSHd tests" -TEST_HOST=$1 -TEST_PORT=$2 +USER=$1 +TEST_HOST=$2 +TEST_PORT=$3 TOTAL=0 SKIPPED=0 # setup set -e ./create_authorized_test_file.sh -./create_sshd_config.sh +./create_sshd_config.sh $USER set +e if [ ! -z "$TEST_HOST" ] && [ ! -z "$TEST_PORT" ]; then @@ -31,7 +32,7 @@ fi run_test() { printf "$1 ... " - ./"$1" "$TEST_HOST" "$TEST_PORT" &> stdout.txt + ./"$1" "$TEST_HOST" "$TEST_PORT" "$USER" &> stdout.txt RESULT=$? TOTAL=$((TOTAL+1)) if [ "$RESULT" == 77 ]; then @@ -73,6 +74,16 @@ else SKIPPED=$((SKIPPED+1)) fi +# these tests run with X509 sshd-config loaded +if [ "$USING_LOCAL_HOST" == 1 ]; then + start_wolfsshd "sshd_config_test_x509" +fi +run_test "sshd_x509_test.sh" +if [ "$USING_LOCAL_HOST" == 1 ]; then + printf "Shutting down test wolfSSHd\n" + stop_wolfsshd +fi + printf "All tests ran, $TOTAL passed, $SKIPPED skipped\n" exit 0 From 31ffa18492cd673beb18958b05f4570f9965b862 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 7 Nov 2023 01:07:41 -0800 Subject: [PATCH 19/35] account for last bit of left over data in pipes after command exits --- apps/wolfsshd/wolfsshd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index c63ef5c21..244f865fb 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1585,7 +1585,20 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } } + + /* check for any left over data in pipes then close them */ if (forcedCmd) { + int readSz; + + readSz = (int)read(stdoutPipe[0], shellBuffer, sizeof shellBuffer); + if (readSz > 0) { + wolfSSH_ChannelIdSend(ssh, shellChannelId, shellBuffer, readSz); + } + + readSz = (int)read(stderrPipe[0], shellBuffer, sizeof shellBuffer); + if (readSz > 0) { + wolfSSH_extended_data_send(ssh, shellBuffer, readSz); + } close(stdoutPipe[0]); close(stderrPipe[0]); } From 2366417b06a277d92df484b24512dce592cf6b3f Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 7 Nov 2023 02:31:10 -0800 Subject: [PATCH 20/35] increase type size for command name and improve handling read of pipes after command exits --- apps/wolfsshd/wolfsshd.c | 24 ++++++++++++++++++++---- wolfssh/internal.h | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 244f865fb..01d17f37a 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1172,11 +1172,15 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, #ifndef EXAMPLE_BUFFER_SZ #define EXAMPLE_BUFFER_SZ 4096 +#endif +#ifndef MAX_IDLE_COUNT + #define MAX_IDLE_COUNT 2 #endif byte shellBuffer[EXAMPLE_BUFFER_SZ]; byte channelBuffer[EXAMPLE_BUFFER_SZ]; char* forcedCmd; int windowFull = 0; + int idle = 0; forcedCmd = wolfSSHD_ConfigGetForcedCmd(usrConf); @@ -1404,7 +1408,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, close(stderrPipe[1]); } - while (ChildRunning) { + while (idle < MAX_IDLE_COUNT) { byte tmp[2]; fd_set readFds; WS_SOCKET_T maxFd; @@ -1412,6 +1416,8 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, int cnt_w; int pending = 0; + idle++; /* increment idle count, gets reset if not idle */ + FD_ZERO(&readFds); FD_SET(sshFd, &readFds); maxFd = sshFd; @@ -1439,6 +1445,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } else { pending = 1; /* found some pending SSH data */ + idle = 0; } if (windowFull || pending || FD_ISSET(sshFd, &readFds)) { @@ -1454,6 +1461,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, if (cnt_r < 0) { rc = wolfSSH_get_error(ssh); if (rc == WS_CHAN_RXD) { + idle = 0; if (lastChannel == shellChannelId) { cnt_r = wolfSSH_ChannelIdRead(ssh, shellChannelId, channelBuffer, @@ -1481,6 +1489,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, shellBuffer, cnt_r); if (cnt_w == WS_WINDOW_FULL) { windowFull = 1; + idle = 0; continue; } else { @@ -1495,12 +1504,13 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, /* This read will return 0 on EOF */ if (cnt_r <= 0) { int err = errno; - if (err != EAGAIN) { + if (err != EAGAIN && err != 0) { break; } } else { if (cnt_r > 0) { + idle = 0; cnt_w = wolfSSH_extended_data_send(ssh, shellBuffer, cnt_r); if (cnt_w == WS_WINDOW_FULL) { @@ -1520,12 +1530,13 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, /* This read will return 0 on EOF */ if (cnt_r <= 0) { int err = errno; - if (err != EAGAIN) { + if (err != EAGAIN && err != 0) { break; } } else { if (cnt_r > 0) { + idle = 0; cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, shellBuffer, cnt_r); if (cnt_w == WS_WINDOW_FULL) { @@ -1544,12 +1555,13 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, /* This read will return 0 on EOF */ if (cnt_r <= 0) { int err = errno; - if (err != EAGAIN) { + if (err != EAGAIN && err != 0) { break; } } else { if (cnt_r > 0) { + idle = 0; cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, shellBuffer, cnt_r); if (cnt_w == WS_WINDOW_FULL) { @@ -1562,6 +1574,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } } + + if (ChildRunning && idle) { + idle = 0; /* waiting on child process */ + } } /* get return value of child process */ diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 631edf107..c16e2c3fe 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -717,7 +717,7 @@ struct WOLFSSH { word32 defaultPeerChannelId; word32 connectChannelId; byte channelName[WOLFSSH_MAX_CHN_NAMESZ]; - byte channelNameSz; + word32 channelNameSz; word32 lastRxId; WOLFSSH_BUFFER inputBuffer; From 903bc98c342e3fc1050ffe3be178a038d07ab238 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 7 Nov 2023 23:33:36 -0800 Subject: [PATCH 21/35] update example client shell settings --- examples/client/common.c | 55 +++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/examples/client/common.c b/examples/client/common.c index 671532a4d..3ae6a7316 100644 --- a/examples/client/common.c +++ b/examples/client/common.c @@ -542,27 +542,46 @@ int ClientSetEcho(int type) } echoInit = 1; } - if (type == 1) { - if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) { - printf("Couldn't restore the terminal settings.\n"); - return -1; - } - } - else { - struct termios newTerm; - memcpy(&newTerm, &originalTerm, sizeof(struct termios)); - - newTerm.c_lflag &= ~ECHO; - if (type == 2) { - newTerm.c_lflag &= ~(ICANON | ECHOE | ECHOK | ECHONL | ISIG); + if (echoInit) { + if (type == 1) { + if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) { + printf("Couldn't restore the terminal settings.\n"); + return -1; + } } else { - newTerm.c_lflag |= (ICANON | ECHONL); - } + struct termios newTerm; + memcpy(&newTerm, &originalTerm, sizeof(struct termios)); + + newTerm.c_lflag &= ~ECHO; + if (type == 2) { + newTerm.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE + | ECHOK | ECHONL | ECHOPRT | NOFLSH | TOSTOP | FLUSHO + | PENDIN | EXTPROC); + + newTerm.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON + | IXOFF | IXANY | IGNBRK | INPCK | PARMRK); + #ifdef IUCLC + newTerm.c_iflag &= ~IUCLC; + #endif + newTerm.c_iflag |= IGNPAR; - if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) { - printf("Couldn't turn off echo.\n"); - return -1; + newTerm.c_oflag &= ~(OPOST | ONOCR | ONLRET); + #ifdef OUCLC + newTerm.c_oflag &= ~OLCUC; + #endif + + newTerm.c_cflag &= ~(CSTOPB | PARENB | PARODD | CLOCAL + | CRTSCTS); + } + else { + newTerm.c_lflag |= (ICANON | ECHONL); + } + + if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) { + printf("Couldn't turn off echo.\n"); + return -1; + } } } #else From ab45a98d18e1c752b61db64b53e30e7f4effd52c Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Wed, 8 Nov 2023 00:10:36 -0800 Subject: [PATCH 22/35] fix for building with QNX --- apps/wolfssh/wolfssh.c | 30 +++++++++++++++++++++++------- examples/client/common.c | 24 ++++++++++++++++++++---- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/apps/wolfssh/wolfssh.c b/apps/wolfssh/wolfssh.c index 21242d7b2..5e216cbe7 100644 --- a/apps/wolfssh/wolfssh.c +++ b/apps/wolfssh/wolfssh.c @@ -162,12 +162,26 @@ static void modes_clear(void) { WOLFSSH_TERMIOS term = oldTerm; - term.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK - | ECHONL | ECHOPRT | NOFLSH | TOSTOP | FLUSHO - | PENDIN | EXTPROC); + term.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE + | ECHOK | ECHONL | NOFLSH | TOSTOP); - term.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF - | IXANY | IGNBRK | INPCK | PARMRK); + /* check macros set for some BSD dependent and missing on + * QNX flags */ +#ifdef ECHOPRT + term.c_lflag &= ~(ECHOPRT); +#endif +#ifdef FLUSHO + term.c_lflag &= ~(FLUSHO); +#endif +#ifdef PENDIN + term.c_lflag &= ~(PENDIN); +#endif +#ifdef EXTPROC + term.c_lflag &= ~(EXTPROC); +#endif + + term.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON + | IXOFF | IXANY | IGNBRK | INPCK | PARMRK); #ifdef IUCLC term.c_iflag &= ~IUCLC; #endif @@ -178,8 +192,10 @@ static void modes_clear(void) term.c_oflag &= ~OLCUC; #endif - term.c_cflag &= ~(CSTOPB | PARENB | PARODD | CLOCAL | CRTSCTS); - + term.c_cflag &= ~(CSTOPB | PARENB | PARODD | CLOCAL); +#ifdef CRTSCTS + term.c_cflag &= ~(CRTSCTS); +#endif tcsetattr(STDIN_FILENO, TCSANOW, &term); } diff --git a/examples/client/common.c b/examples/client/common.c index 3ae6a7316..da2da1ea9 100644 --- a/examples/client/common.c +++ b/examples/client/common.c @@ -556,8 +556,22 @@ int ClientSetEcho(int type) newTerm.c_lflag &= ~ECHO; if (type == 2) { newTerm.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE - | ECHOK | ECHONL | ECHOPRT | NOFLSH | TOSTOP | FLUSHO - | PENDIN | EXTPROC); + | ECHOK | ECHONL | NOFLSH | TOSTOP); + + /* check macros set for some BSD dependent and not missing on + * QNX flags */ + #ifdef ECHOPRT + newTerm.c_lflag &= ~(ECHOPRT); + #endif + #ifdef FLUSHO + newTerm.c_lflag &= ~(FLUSHO); + #endif + #ifdef PENDIN + newTerm.c_lflag &= ~(PENDIN); + #endif + #ifdef EXTPROC + newTerm.c_lflag &= ~(EXTPROC); + #endif newTerm.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF | IXANY | IGNBRK | INPCK | PARMRK); @@ -571,8 +585,10 @@ int ClientSetEcho(int type) newTerm.c_oflag &= ~OLCUC; #endif - newTerm.c_cflag &= ~(CSTOPB | PARENB | PARODD | CLOCAL - | CRTSCTS); + newTerm.c_cflag &= ~(CSTOPB | PARENB | PARODD | CLOCAL); + #ifdef CRTSCTS + newTerm.c_cflag &= ~(CRTSCTS); + #endif } else { newTerm.c_lflag |= (ICANON | ECHONL); From 521981ea1b00e85b0c0ee5df0041f94123639dfd Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 11 Dec 2023 09:58:51 -0800 Subject: [PATCH 23/35] check in x509 test script --- apps/wolfsshd/test/sshd_x509_test.sh | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100755 apps/wolfsshd/test/sshd_x509_test.sh diff --git a/apps/wolfsshd/test/sshd_x509_test.sh b/apps/wolfsshd/test/sshd_x509_test.sh new file mode 100755 index 000000000..3ba754941 --- /dev/null +++ b/apps/wolfsshd/test/sshd_x509_test.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# sshd local test + +PWD=`pwd` +cd ../../.. + +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then + echo "expecting host, port and user as arguments" + echo "./sshd_x509_text.sh 127.0.0.1 22222 user" + exit -1 +fi + +TEST_CLIENT="./examples/client/client" +PRIVATE_KEY="./keys/$3-key.der" +PUBLIC_KEY="./keys/$3-cert.der" +CA_CERT="./keys/ca-cert-ecc.der" + +set -e +echo "$TEST_CLIENT -c 'pwd' -u $3 -i $PRIVATE_KEY -J $PUBLIC_KEY -A $CA_CERT -h \"$1\" -p \"$2\"" +$TEST_CLIENT -c 'pwd' -u $3 -i "$PRIVATE_KEY" -J "$PUBLIC_KEY" -A "$CA_CERT" -h "$1" -p "$2" +set +e + +#rm -f error.txt +#echo "$TEST_CLIENT -c 'ls error' -u $3 -i $PRIVATE_KEY -J $PUBLIC_KEY -A $CA_CERT -h \"$1\" -p \"$2\" 2> error.txt" +#$TEST_CLIENT -c 'ls error' -u $3 -i "$PRIVATE_KEY" -J "$PUBLIC_KEY" -A "$CA_CERT" -h "$1" -p "$2" 2> error.txt +# +## check stderr output was caught +#if [ ! -s error.txt ]; then +# echo "No stderr data was found when expected!!" +# cd $PWD +# exit 1 +#fi + +cd $PWD +exit 0 + + From 126a884affd75faa17f2560094878fcd6936790a Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 26 Jan 2024 14:35:50 -0700 Subject: [PATCH 24/35] adjust sshd test for user name --- .github/workflows/sshd-test.yml | 2 +- apps/wolfsshd/test/run_all_sshd_tests.sh | 8 +++++++- apps/wolfsshd/test/sshd_x509_test.sh | 21 +++++++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.github/workflows/sshd-test.yml b/.github/workflows/sshd-test.yml index 42287a66f..828344af8 100644 --- a/.github/workflows/sshd-test.yml +++ b/.github/workflows/sshd-test.yml @@ -28,5 +28,5 @@ jobs: - name: make check run: make check - name: run wolfSSHd tests - run: sudo ./run_all_sshd_tests.sh + run: sudo ./run_all_sshd_tests.sh root working-directory: ./apps/wolfsshd/test diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index aac061746..746762bb7 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -2,9 +2,15 @@ echo "Running all wolfSSHd tests" -USER=$1 +if [ -z "$1" ]; then + USER=$USER +else + USER=$1 +fi + TEST_HOST=$2 TEST_PORT=$3 + TOTAL=0 SKIPPED=0 diff --git a/apps/wolfsshd/test/sshd_x509_test.sh b/apps/wolfsshd/test/sshd_x509_test.sh index 3ba754941..dd9005f53 100755 --- a/apps/wolfsshd/test/sshd_x509_test.sh +++ b/apps/wolfsshd/test/sshd_x509_test.sh @@ -21,16 +21,17 @@ echo "$TEST_CLIENT -c 'pwd' -u $3 -i $PRIVATE_KEY -J $PUBLIC_KEY -A $CA_CERT -h $TEST_CLIENT -c 'pwd' -u $3 -i "$PRIVATE_KEY" -J "$PUBLIC_KEY" -A "$CA_CERT" -h "$1" -p "$2" set +e -#rm -f error.txt -#echo "$TEST_CLIENT -c 'ls error' -u $3 -i $PRIVATE_KEY -J $PUBLIC_KEY -A $CA_CERT -h \"$1\" -p \"$2\" 2> error.txt" -#$TEST_CLIENT -c 'ls error' -u $3 -i "$PRIVATE_KEY" -J "$PUBLIC_KEY" -A "$CA_CERT" -h "$1" -p "$2" 2> error.txt -# -## check stderr output was caught -#if [ ! -s error.txt ]; then -# echo "No stderr data was found when expected!!" -# cd $PWD -# exit 1 -#fi +rm -f error.txt +echo "$TEST_CLIENT -c 'ls error' -u $3 -i $PRIVATE_KEY -J $PUBLIC_KEY -A $CA_CERT -h \"$1\" -p \"$2\" 2> error.txt" +$TEST_CLIENT -c 'ls error' -u $3 -i "$PRIVATE_KEY" -J "$PUBLIC_KEY" -A "$CA_CERT" -h "$1" -p "$2" 2> error.txt + +# check stderr output was caught +if [ ! -s error.txt ]; then + echo "No stderr data was found when expected!!" + cd $PWD + exit 1 +fi +rm -f error.txt cd $PWD exit 0 From b256522f5b68a7a0063fe33d1d078c7d68494f13 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Sat, 27 Jan 2024 13:03:10 +0900 Subject: [PATCH 25/35] fix WOLFSSH_NO_RSA --- examples/client/common.c | 4 ++-- examples/sftpclient/sftpclient.c | 3 ++- src/internal.c | 2 +- tests/api.c | 1 + wolfssh/internal.h | 2 ++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/client/common.c b/examples/client/common.c index 671532a4d..5a2c2ba63 100644 --- a/examples/client/common.c +++ b/examples/client/common.c @@ -642,7 +642,7 @@ int ClientUseCert(const char* certName) * returns 0 on success */ int ClientSetPrivateKey(const char* privKeyName, int userEcc) { - int ret; + int ret = 0; if (privKeyName == NULL) { if (userEcc) { @@ -682,7 +682,7 @@ int ClientSetPrivateKey(const char* privKeyName, int userEcc) * returns 0 on success */ int ClientUsePubKey(const char* pubKeyName, int userEcc) { - int ret; + int ret = 0; if (pubKeyName == NULL) { byte* p = userPublicKey; diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 38b079823..01a2308b6 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -1128,6 +1128,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) socklen_t clientAddrSz = sizeof(clientAddr); int ret; int ch; + int userEcc = 0; /* int peerEcc = 0; */ word16 port = wolfSshPort; char* host = (char*)wolfSshIp; @@ -1262,7 +1263,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) } #endif - ret = ClientSetPrivateKey(privKeyName, 0); + ret = ClientSetPrivateKey(privKeyName, userEcc); if (ret != 0) { err_sys("Error setting private key"); } diff --git a/src/internal.c b/src/internal.c index 4e69277fb..096bf9ddd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6829,7 +6829,7 @@ static int DoChannelOpen(WOLFSSH* ssh, word32 typeSz; char type[32]; byte typeId = ID_UNKNOWN; - word32 peerChannelId; + word32 peerChannelId = 0; word32 peerInitialWindowSz; word32 peerMaxPacketSz; #ifdef WOLFSSH_FWD diff --git a/tests/api.c b/tests/api.c index b7f26063a..9aaf12953 100644 --- a/tests/api.c +++ b/tests/api.c @@ -746,6 +746,7 @@ static void test_wolfSSH_ReadKey(void) #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 /* OpenSSH Format, ecdsa-sha2-nistp256, private, need alloc */ + (void)keyCheck; key = NULL; keySz = 0; keyType = NULL; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index fe435b33e..001116cb0 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -1204,9 +1204,11 @@ WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH*, int, const char*, char*, word32, WOLFSSH_LOCAL int wolfSSH_CleanPath(WOLFSSH* ssh, char* in); +#ifndef WOLFSSH_NO_RSA WOLFSSH_LOCAL int wolfSSH_RsaVerify(byte *sig, word32 sigSz, const byte* digest, word32 digestSz, RsaKey* key, void* heap, const char* loc); +#endif WOLFSSH_LOCAL void DumpOctetString(const byte*, word32); WOLFSSH_LOCAL int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz); WOLFSSH_LOCAL void AddAssign64(word32*, word32); From 7156ac81e0388df0b8a434047e388e1104593355 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 29 Jan 2024 14:47:34 -0700 Subject: [PATCH 26/35] adjust test socket close down and pull of zephyr sdk --- .github/workflows/zephyr.yml | 6 +++--- tests/api.c | 5 +++++ zephyr/samples/tests/sample.yaml | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 40649231d..1221e120d 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -66,10 +66,10 @@ jobs: - name: Install zephyr SDK run: | - wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${{ matrix.config.zephyr-sdk }}/zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64.tar.xz - tar xf zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64.tar.xz + wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${{ matrix.config.zephyr-sdk }}/zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64_minimal.tar.xz + tar xf zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64_minimal.tar.xz cd zephyr-sdk-${{ matrix.config.zephyr-sdk }} - ./setup.sh -h -c + ./setup.sh -h -c -t x86_64-zephyr-elf - name: Run wolfssh tests id: wolfssh-test diff --git a/tests/api.c b/tests/api.c index b7f26063a..5ef8010aa 100644 --- a/tests/api.c +++ b/tests/api.c @@ -953,6 +953,7 @@ static void test_wolfSSH_SFTP_SendReadPacket(void) func_args ser; tcp_ready ready; int argsCount; + int clientFd; const char* args[10]; WOLFSSH_CTX* ctx = NULL; @@ -1061,6 +1062,10 @@ static void test_wolfSSH_SFTP_SendReadPacket(void) AssertIntEQ(argsCount, WS_SUCCESS); + /* close client socket down */ + clientFd = wolfSSH_get_fd(ssh); + close(clientFd); + wolfSSH_free(ssh); wolfSSH_CTX_free(ctx); #ifdef WOLFSSH_ZEPHYR diff --git a/zephyr/samples/tests/sample.yaml b/zephyr/samples/tests/sample.yaml index f216d6345..4f6f359cf 100644 --- a/zephyr/samples/tests/sample.yaml +++ b/zephyr/samples/tests/sample.yaml @@ -9,7 +9,7 @@ common: - "Zephyr wolfSSH tests passed" tests: sample.lib.wolfssh_tests: - timeout: 50 + timeout: 200 platform_allow: qemu_x86 integration_platforms: - qemu_x86 From b662bcaaf162c49808c2167a5d91b716740ca8c7 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 29 Jan 2024 16:40:35 -0700 Subject: [PATCH 27/35] fix return value for test shell scripts --- apps/wolfsshd/test/error_return.sh | 2 +- apps/wolfsshd/test/sshd_exec_test.sh | 2 +- apps/wolfsshd/test/sshd_forcedcmd_test.sh | 4 ++-- apps/wolfsshd/test/sshd_x509_test.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/wolfsshd/test/error_return.sh b/apps/wolfsshd/test/error_return.sh index 0c00336e5..8c876324b 100755 --- a/apps/wolfsshd/test/error_return.sh +++ b/apps/wolfsshd/test/error_return.sh @@ -13,7 +13,7 @@ PUBLIC_KEY="./keys/hansel-key-ecc.pub" if [ -z "$1" ] || [ -z "$2" ]; then echo "expecting host and port as arguments" echo "./error_return.sh 127.0.0.1 22222" - exit -1 + exit 1 fi echo "$TEST_CLIENT -c 'bash -c \"(exit 2)\"' -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h \"$1\" -p \"$2\"" diff --git a/apps/wolfsshd/test/sshd_exec_test.sh b/apps/wolfsshd/test/sshd_exec_test.sh index 2fde3bda2..889bc24a2 100755 --- a/apps/wolfsshd/test/sshd_exec_test.sh +++ b/apps/wolfsshd/test/sshd_exec_test.sh @@ -13,7 +13,7 @@ PUBLIC_KEY="./keys/hansel-key-ecc.pub" if [ -z "$1" ] || [ -z "$2" ]; then echo "expecting host and port as arguments" echo "./sshd_exec_test.sh 127.0.0.1 22222" - exit -1 + exit 1 fi set -e diff --git a/apps/wolfsshd/test/sshd_forcedcmd_test.sh b/apps/wolfsshd/test/sshd_forcedcmd_test.sh index 47687fb9a..645307f26 100755 --- a/apps/wolfsshd/test/sshd_forcedcmd_test.sh +++ b/apps/wolfsshd/test/sshd_forcedcmd_test.sh @@ -5,7 +5,7 @@ if [ -z "$1" ] || [ -z "$2" ]; then echo "expecting host and port as arguments" echo "./sshd_exec_test.sh 127.0.0.1 22222" - exit -1 + exit 1 fi PWD=`pwd` @@ -42,7 +42,7 @@ cat $RESULT | grep bob RESULT=$? if [ "$RESULT" == 0 ]; then echo "Shell login should fail with forced command" - exit -1 + exit 1 fi set -e diff --git a/apps/wolfsshd/test/sshd_x509_test.sh b/apps/wolfsshd/test/sshd_x509_test.sh index dd9005f53..991e5d849 100755 --- a/apps/wolfsshd/test/sshd_x509_test.sh +++ b/apps/wolfsshd/test/sshd_x509_test.sh @@ -8,7 +8,7 @@ cd ../../.. if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then echo "expecting host, port and user as arguments" echo "./sshd_x509_text.sh 127.0.0.1 22222 user" - exit -1 + exit 1 fi TEST_CLIENT="./examples/client/client" From bb81ad0afc32b1bbef30494f6c871c9b2168fb8b Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Wed, 31 Jan 2024 08:18:16 +0900 Subject: [PATCH 28/35] additional gate for RSA --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 096bf9ddd..49b21da8a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1034,6 +1034,7 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap) } +#ifndef WOLFSSH_NO_RSA /* * Utility function to read an Mpint from the stream directly into a mp_int. */ @@ -1052,7 +1053,6 @@ static INLINE int GetMpintToMp(mp_int* mp, } -#ifndef WOLFSSH_NO_RSA /* * For the given RSA key, calculate p^-1 and q^-1. wolfCrypt's RSA * code expects them, but the OpenSSH format key doesn't store them. From 53ce7d718bd9d4da2c139a88da421cff5c438435 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 1 Feb 2024 15:13:16 -0800 Subject: [PATCH 29/35] RSA Verify Fix 1. Switch from wc_RsaSSL_VerifyInline() to wc_RsaSSL_Verify(). Fixes a bad free. --- src/internal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/internal.c b/src/internal.c index dbb601db4..8c710d193 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9726,25 +9726,25 @@ int wolfSSH_RsaVerify(byte *sig, word32 sigSz, const byte* digest, word32 digestSz, RsaKey* key, void* heap, const char* loc) { - byte* checkSig; + byte* check; int ret = WS_SUCCESS; - checkSig = (byte*)WMALLOC(sigSz, heap, DYNTYPE_TEMP); - if (checkSig == NULL) { + check = (byte*)WMALLOC(digestSz, heap, DYNTYPE_TEMP); + if (check == NULL) { ret = WS_MEMORY_E; } else { int checkSz; - checkSz = wc_RsaSSL_VerifyInline(sig, sigSz, &checkSig, key); + checkSz = wc_RsaSSL_Verify(sig, sigSz, check, digestSz, key); if (checkSz < 0 || (word32)checkSz != digestSz - || WMEMCMP(digest, checkSig, digestSz) != 0) { + || WMEMCMP(digest, check, digestSz) != 0) { WLOG(WS_LOG_DEBUG, "%s: %s", loc, "Bad RSA Sign Verify"); ret = WS_RSA_E; } - ForceZero(checkSig, sigSz); - WFREE(checkSig, heap, DYNTYPE_TEMP); + ForceZero(check, digestSz); + WFREE(check, heap, DYNTYPE_TEMP); } return ret; From 8ce9d164ca920d4f56d240e6fa0e7812b84d6712 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 2 Feb 2024 09:46:41 -0700 Subject: [PATCH 30/35] fix windows build with sshd --- apps/wolfsshd/wolfsshd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 01d17f37a..6b9c9e1d4 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -904,8 +904,8 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, CreatePipe(&cnslIn, &ptyIn, NULL, 0); CreatePipe(&ptyOut, &cnslOut, NULL, 0); - cord.X = ssh->curX; - cord.Y = ssh->curY; + cord.X = ssh->widthChar; + cord.Y = ssh->heightRows; /* Sanity check on cord values, if 0 than assume was not set. * (can happen with exec and not req-pty message) From 23e8405c43df6de2cf2b93a938d51883caa128b7 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 2 Feb 2024 10:11:33 -0700 Subject: [PATCH 31/35] if not a directory then set file type with windows --- src/wolfsftp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 0d62ade4a..b2ecf1fd6 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -4489,7 +4489,8 @@ int SFTP_GetAttributes(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr, atr->flags |= WOLFSSH_FILEATRB_PERM; atr->per = 0555 | (stats.dwFileAttributes | FILE_ATTRIBUTE_READONLY ? 0 : 0200); - atr->per |= (stats.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0x4000:0; + atr->per |= (stats.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0x4000: + FILEATRB_PER_FILE; #if 0 /* @TODO handle the constellation of possible Windows FILETIMEs */ From 46cdfc570ddad8d2fb9ed283ca76ace217a106d5 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Sat, 3 Feb 2024 00:24:04 -0700 Subject: [PATCH 32/35] set pipes as non blocking before last read --- apps/wolfsshd/wolfsshd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 6b9c9e1d4..a7ef2f0a5 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1606,11 +1606,15 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, if (forcedCmd) { int readSz; + fcntl(stdoutPipe[0], F_SETFL, fcntl(stdoutPipe[0], F_GETFL) + | O_NONBLOCK); readSz = (int)read(stdoutPipe[0], shellBuffer, sizeof shellBuffer); if (readSz > 0) { wolfSSH_ChannelIdSend(ssh, shellChannelId, shellBuffer, readSz); } + fcntl(stderrPipe[0], F_SETFL, fcntl(stderrPipe[0], F_GETFL) + | O_NONBLOCK); readSz = (int)read(stderrPipe[0], shellBuffer, sizeof shellBuffer); if (readSz > 0) { wolfSSH_extended_data_send(ssh, shellBuffer, readSz); From c157d56d712808461570c947282ce6b9e12fe0ea Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 2 Feb 2024 10:38:10 -0700 Subject: [PATCH 33/35] add windows github action build test --- .github/workflows/windows-check.yml | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/windows-check.yml diff --git a/.github/workflows/windows-check.yml b/.github/workflows/windows-check.yml new file mode 100644 index 000000000..044988f3b --- /dev/null +++ b/.github/workflows/windows-check.yml @@ -0,0 +1,66 @@ +name: Windows Build Test + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +env: + WOLFSSL_SOLUTION_FILE_PATH: wolfssl64.sln + SOLUTION_FILE_PATH: wolfssh.sln + USER_SETTINGS_H_NEW: wolfssh/ide/winvs/user_settings.h + USER_SETTINGS_H: wolfssl/IDE/WIN/user_settings.h + INCLUDE_DIR: wolfssh + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + WOLFSSL_BUILD_CONFIGURATION: Release + WOLFSSH_BUILD_CONFIGURATION: Release + BUILD_PLATFORM: x64 + TARGET_PLATFORM: 10 + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + with: + repository: wolfssl/wolfssl + path: wolfssl + + - uses: actions/checkout@master + with: + path: wolfssh + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1 + + - name: Restore wolfSSL NuGet packages + working-directory: ${{env.GITHUB_WORKSPACE}}wolfssl + run: nuget restore ${{env.WOLFSSL_SOLUTION_FILE_PATH}} + + - name: updated user_settings.h for sshd and x509 + working-directory: ${{env.GITHUB_WORKSPACE}} + run: cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}} + + - name: replace wolfSSL user_settings.h with wolfSSH user_settings.h + working-directory: ${{env.GITHUB_WORKSPACE}} + run: get-content ${{env.USER_SETTINGS_H_NEW}} | %{$_ -replace "if 0","if 1"} + + - name: Build wolfssl library + working-directory: ${{env.GITHUB_WORKSPACE}}wolfssl + run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:Configuration=${{env.WOLFSSL_BUILD_CONFIGURATION}} /t:wolfssl ${{env.WOLFSSL_SOLUTION_FILE_PATH}} + + - name: Restore NuGet packages + working-directory: ${{env.GITHUB_WORKSPACE}}wolfssh\ide\winvs + run: nuget restore ${{env.SOLUTION_FILE_PATH}} + + - name: Build wolfssh + working-directory: ${{env.GITHUB_WORKSPACE}}wolfssh\ide\winvs + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:WindowsTargetPlatformVersion=${{env.TARGET_PLATFORM}} /p:Configuration=${{env.WOLFSSH_BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} + From 1e982a7a22e845131da887d67866a3e82171ace8 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Thu, 15 Feb 2024 06:07:10 -0700 Subject: [PATCH 34/35] fix for file offset when larger than word32 size --- src/internal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 8c710d193..e7020fbfc 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14379,7 +14379,9 @@ void AddAssign64(word32* addend1, word32 addend2) { if (addend1[0] > (WOLFSSL_MAX_32BIT - addend2)) { addend1[1]++; - addend1[0] = addend2 - (WOLFSSL_MAX_32BIT- addend1[0]); + + /* -1 to account for roll over digit */ + addend1[0] = addend2 - (WOLFSSL_MAX_32BIT- addend1[0]) - 1; } else { addend1[0] += addend2; From cd3130fa7e23fa736fc6775a2984a770d2d87934 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Thu, 15 Feb 2024 09:32:58 -0700 Subject: [PATCH 35/35] add large sftp file transfer test case --- .github/workflows/sshd-test.yml | 2 +- apps/wolfsshd/test/run_all_sshd_tests.sh | 1 + apps/wolfsshd/test/sshd_large_sftp_test.sh | 40 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100755 apps/wolfsshd/test/sshd_large_sftp_test.sh diff --git a/.github/workflows/sshd-test.yml b/.github/workflows/sshd-test.yml index 828344af8..1a715ccc5 100644 --- a/.github/workflows/sshd-test.yml +++ b/.github/workflows/sshd-test.yml @@ -22,7 +22,7 @@ jobs: - name: autogen run: ./autogen.sh - name: configure - run: ./configure --enable-all CPPFLAGS=-DWOLFSSH_NO_FPKI + run: ./configure --enable-all CPPFLAGS="-DWOLFSSH_NO_FPKI -DWOLFSSH_NO_SFTP_TIMEOUT -DWOLFSSH_MAX_SFTP_RW=4000000" - name: make run: make - name: make check diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 746762bb7..d103939c4 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -59,6 +59,7 @@ run_test() { run_test "sshd_exec_test.sh" run_test "sshd_term_size_test.sh" +run_test "sshd_large_sftp_test.sh" #Github actions needs resolved for these test cases #run_test "error_return.sh" diff --git a/apps/wolfsshd/test/sshd_large_sftp_test.sh b/apps/wolfsshd/test/sshd_large_sftp_test.sh new file mode 100755 index 000000000..0a3144273 --- /dev/null +++ b/apps/wolfsshd/test/sshd_large_sftp_test.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# sshd local test + +PWD=`pwd` +cd ../../.. + +TEST_SFTP_CLIENT="./examples/sftpclient/wolfsftp" +USER=`whoami` +PRIVATE_KEY="./keys/hansel-key-ecc.der" +PUBLIC_KEY="./keys/hansel-key-ecc.pub" + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "expecting host and port as arguments" + echo "./sshd_exec_test.sh 127.0.0.1 22222" + exit 1 +fi + + +# create a large file with random data (larger than word32 max value) +head -c 4400000010 < /dev/random > large-random.txt + +set -e +echo "$TEST_SFTP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -g -l large-random.txt -r `pwd`/large-random-2.txt -h \"$1\" -p \"$2\"" +$TEST_SFTP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -g -l large-random.txt -r `pwd`/large-random-2.txt -h "$1" -p "$2" + +cmp large-random.txt large-random-2.txt +RESULT=$? +if [ "$RESULT" != "0" ]; then + echo "files did not match when compared" + exit 1 +fi +rm -f large-random.txt +rm -f large-random-2.txt + +set +e + +cd $PWD +exit 0 +