Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 88 additions & 8 deletions apps/wolfsshd/wolfsshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
#endif
byte shellBuffer[WOLFSSHD_SHELL_BUFFER_SZ];
int cnt_r, cnt_w;
int windowFull = 0; /* bytes left in shellBuffer that a prior send could
* not pass on to wolfSSH yet. This happens with window
* full, rekey, or want-write; resent before reading
* more so the buffered data is not overwritten. */
HANDLE ptyIn = NULL, ptyOut = NULL;
HANDLE cnslIn = NULL, cnslOut = NULL;
STARTUPINFOEX ext;
Expand Down Expand Up @@ -1063,7 +1067,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
continue;
}
}
break;
/* keep looping while buffered data still needs to be
* flushed to the SSH channel */
if (!windowFull)
break;
}
}
if (wolfSSH_stream_peek(ssh, tmp, 1) <= 0) {
Expand Down Expand Up @@ -1123,7 +1130,30 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}
}

if (readPending) {
/* if a previous send could not complete, resend the buffered data
* before reading more so shellBuffer is not overwritten */
if (windowFull) {
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, windowFull);
if (cnt_w == WS_WINDOW_FULL || cnt_w == WS_REKEYING ||
cnt_w == WS_WANT_WRITE) {
continue;
}
else if (cnt_w < 0) {
break;
}
else {
windowFull -= cnt_w;
if (windowFull > 0) {
WMEMMOVE(shellBuffer, shellBuffer + cnt_w, windowFull);
continue;
}
if (windowFull < 0)
windowFull = 0;
}
}

if (readPending && !windowFull) {
WMEMSET(shellBuffer, 0, WOLFSSHD_SHELL_BUFFER_SZ);

if (ReadFile(ptyOut, shellBuffer, WOLFSSHD_SHELL_BUFFER_SZ, &cnt_r,
Expand All @@ -1137,8 +1167,19 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
if (cnt_r > 0) {
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, cnt_r);
if (cnt_w < 0)
if (cnt_w > 0 && cnt_w < cnt_r) { /* partial send */
windowFull = cnt_r - cnt_w;
WMEMMOVE(shellBuffer, shellBuffer + cnt_w,
windowFull);
}
else if (cnt_w == WS_WINDOW_FULL ||
cnt_w == WS_REKEYING ||
cnt_w == WS_WANT_WRITE) {
windowFull = cnt_r; /* save amount to be sent */
}
else if (cnt_w < 0) {
break;
}
}
}
}
Expand Down Expand Up @@ -1234,6 +1275,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
int windowFull = 0; /* Contains size of bytes from shellBuffer that did
* not get passed on to wolfSSH yet. This happens
* with window full errors or when rekeying. */
int windowFullExt = 0; /* Nonzero when the bytes held in shellBuffer
* belong to the extended (stderr) data stream
* and must be resent with
* wolfSSH_extended_data_send(). */
int wantWrite = 0;
int peerConnected = 1;
int stdoutEmpty = 0;
Expand Down Expand Up @@ -1543,8 +1588,14 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}

rc = select((int)maxFd + 1, &readFds, &writeFds, NULL, NULL);
if (rc == -1)
if (rc == -1) {
/* Signal (e.g. SIGCHLD from child exit) interrupted select.
* Re-evaluate the loop condition so any pending windowFull
* data and remaining pipe contents still get drained. */
if (errno == EINTR)
continue;
Comment thread
ejohnstown marked this conversation as resolved.
break;
}
}
else {
pending = 1; /* found some pending SSH data */
Expand Down Expand Up @@ -1623,15 +1674,25 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,

/* if the window was previously full, try resending the data */
if (windowFull) {
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, windowFull);
if (windowFullExt) {
cnt_w = wolfSSH_extended_data_send(ssh, shellBuffer,
windowFull);
}
else {
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, windowFull);
}
if (cnt_w == WS_WINDOW_FULL || cnt_w == WS_REKEYING) {
continue;
}
Comment thread
ejohnstown marked this conversation as resolved.
else if (cnt_w == WS_WANT_WRITE) {
wantWrite = 1;
continue;
}
else if (cnt_w < 0) {
kill(childPid, SIGINT);
break;
}
else {
windowFull -= cnt_w;
if (windowFull > 0) {
Expand All @@ -1640,6 +1701,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}
if (windowFull < 0)
windowFull = 0;
windowFullExt = 0;
}
}

Expand All @@ -1660,15 +1722,22 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
cnt_r);
if (cnt_w > 0 && cnt_w < cnt_r) { /* partial send */
windowFull = cnt_r - cnt_w;
windowFullExt = 1;
WMEMMOVE(shellBuffer, shellBuffer + cnt_w,
windowFull);
/* don't let the stdout read below trample the
* buffered stderr remainder */
continue;
}
else if (cnt_w == WS_WINDOW_FULL ||
cnt_w == WS_REKEYING) {
windowFull = cnt_r; /* save amount to be sent */
windowFullExt = 1;
continue;
}
else if (cnt_w == WS_WANT_WRITE) {
windowFull = cnt_r;
windowFullExt = 1;
wantWrite = 1;
continue;
}
Expand Down Expand Up @@ -1698,15 +1767,19 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
shellBuffer, cnt_r);
if (cnt_w > 0 && cnt_w < cnt_r) { /* partial send */
windowFull = cnt_r - cnt_w;
windowFullExt = 0;
WMEMMOVE(shellBuffer, shellBuffer + cnt_w,
windowFull);
}
else if (cnt_w == WS_WINDOW_FULL ||
cnt_w == WS_REKEYING) {
windowFull = cnt_r; /* save amount to be sent */
windowFullExt = 0;
continue;
}
else if (cnt_w == WS_WANT_WRITE) {
windowFull = cnt_r;
windowFullExt = 0;
wantWrite = 1;
continue;
}
Expand All @@ -1721,28 +1794,35 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
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) {
/* Treat a 0 return as EOF so the loop can shut down. */
if (cnt_r < 0) {
int err = errno;
if (err != EAGAIN && err != 0) {
break;
}
}
else if (cnt_r == 0) {
stdoutEmpty = 1;
}
else {
if (cnt_r > 0) {
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, cnt_r);
if (cnt_w > 0 && cnt_w < cnt_r) { /* partial send */
windowFull = cnt_r - cnt_w;
windowFullExt = 0;
WMEMMOVE(shellBuffer, shellBuffer + cnt_w,
windowFull);
}
else if (cnt_w == WS_WINDOW_FULL ||
cnt_w == WS_REKEYING) {
windowFull = cnt_r;
windowFullExt = 0;
continue;
}
else if (cnt_w == WS_WANT_WRITE) {
windowFull = cnt_r;
windowFullExt = 0;
wantWrite = 1;
continue;
}
Expand Down
Loading