Skip to content

Commit

Permalink
adjust shutdown for sending exit status cleanly
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobBarthelmeh committed Nov 5, 2023
1 parent 7e2882c commit 1c05d41
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 80 deletions.
10 changes: 7 additions & 3 deletions apps/wolfsshd/wolfsshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -1420,7 +1420,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");
Expand Down Expand Up @@ -1670,9 +1670,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) {
Expand All @@ -1682,6 +1685,7 @@ static void* HandleConnection(void* arg)
}
}

/* check if there is a response to the shutdown */
wolfSSH_free(ssh);
if (conn != NULL) {
WCLOSESOCKET(conn->fd);
Expand Down
7 changes: 5 additions & 2 deletions examples/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
}
}
Expand All @@ -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)
Expand Down
58 changes: 0 additions & 58 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -13362,64 +13362,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
Expand Down
51 changes: 35 additions & 16 deletions src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,24 +950,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");
Expand Down Expand Up @@ -1376,18 +1395,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

Expand Down
2 changes: 1 addition & 1 deletion wolfssh/ssh.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,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 {
Expand Down

0 comments on commit 1c05d41

Please sign in to comment.