Skip to content

Commit

Permalink
Merge pull request #718 from ejohnstown/wolfsshd-closure
Browse files Browse the repository at this point in the history
wolfSSHd Connection Closure
  • Loading branch information
douzzer authored Jul 16, 2024
2 parents 9054adf + 6c69c12 commit e3bed88
Showing 1 changed file with 67 additions and 27 deletions.
94 changes: 67 additions & 27 deletions apps/wolfsshd/wolfsshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ static byte* getBufferFromFile(const char* fileName, word32* bufSz, void* heap)

if (WFOPEN(NULL, &file, fileName, "rb") != 0)
return NULL;
WFSEEK(NULL, file, 0, XSEEK_END);
WFSEEK(NULL, file, 0, WSEEK_END);
fileSz = (word32)WFTELL(NULL, file);
WREWIND(NULL, file);

Expand Down Expand Up @@ -1158,7 +1158,14 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
byte channelBuffer[EXAMPLE_BUFFER_SZ];
char* forcedCmd;
int windowFull = 0;
int idle = 0;
int peerConnected = 1;
int stdoutEmpty = 0;

childFd = -1;
stdoutPipe[0] = -1;
stdoutPipe[1] = -1;
stderrPipe[0] = -1;
stderrPipe[1] = -1;

forcedCmd = wolfSSHD_ConfigGetForcedCmd(usrConf);

Expand All @@ -1168,7 +1175,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
forcedCmd = (char*)subCmd;
}

if (forcedCmd != NULL && XSTRCMP(forcedCmd, "internal-sftp") == 0) {
if (forcedCmd != NULL && WSTRCMP(forcedCmd, "internal-sftp") == 0) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Only SFTP connections allowed for user "
"%s", wolfSSH_GetUsername(ssh));
Expand Down Expand Up @@ -1216,6 +1223,8 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
if (forcedCmd) {
close(stdoutPipe[0]);
close(stderrPipe[0]);
stdoutPipe[0] = -1;
stderrPipe[0] = -1;
if (dup2(stdoutPipe[1], STDOUT_FILENO) == -1) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error redirecting stdout pipe");
Expand Down Expand Up @@ -1288,9 +1297,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
setenv("SHELL", pPasswd->pw_shell, 1);

if (pPasswd->pw_shell) {
word32 shellSz = (word32)WSTRLEN(pPasswd->pw_shell);

if (shellSz < sizeof(shell)) {
if (WSTRLEN(pPasswd->pw_shell) < sizeof(shell)) {
char* cursor;
char* start;

Expand All @@ -1313,12 +1320,11 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}

/* default to /bin/sh if user shell is not set */
WMEMSET(cmd, 0, sizeof(cmd));
if (XSTRLEN(pPasswd->pw_shell) == 0) {
XSNPRINTF(cmd, sizeof(cmd), "%s", "/bin/sh");
if (pPasswd->pw_shell && WSTRLEN(pPasswd->pw_shell)) {
WSNPRINTF(cmd, sizeof(cmd), "%s", pPasswd->pw_shell);
}
else {
XSNPRINTF(cmd, sizeof(cmd),"%s", pPasswd->pw_shell);
WSNPRINTF(cmd, sizeof(cmd), "%s", "/bin/sh");
}

errno = 0;
Expand Down Expand Up @@ -1387,20 +1393,24 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
close(stderrPipe[1]);
}

while (idle < MAX_IDLE_COUNT) {
while (ChildRunning || windowFull || !stdoutEmpty || peerConnected) {
byte tmp[2];
fd_set readFds;
fd_set writeFds;
WS_SOCKET_T maxFd;
int cnt_r;
int cnt_w;
int pending = 0;

idle++; /* increment idle count, gets reset if not idle */

FD_ZERO(&readFds);
FD_SET(sshFd, &readFds);
maxFd = sshFd;

FD_ZERO(&writeFds);
if (windowFull) {
FD_SET(sshFd, &writeFds);
}

/* select on stdout/stderr pipes with forced commands */
if (forcedCmd) {
FD_SET(stdoutPipe[0], &readFds);
Expand All @@ -1418,18 +1428,18 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}

if (wolfSSH_stream_peek(ssh, tmp, 1) <= 0) {
rc = select((int)maxFd + 1, &readFds, NULL, NULL, NULL);
rc = select((int)maxFd + 1, &readFds, &writeFds, NULL, NULL);
if (rc == -1)
break;
}
else {
pending = 1; /* found some pending SSH data */
idle = 0;
}

if (windowFull || pending || FD_ISSET(sshFd, &readFds)) {
word32 lastChannel = 0;

windowFull = 0;
/* The following tries to read from the first channel inside
the stream. If the pending data in the socket is for
another channel, this will return an error with id
Expand All @@ -1440,7 +1450,6 @@ 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,
Expand All @@ -1454,6 +1463,11 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}
}
else if (rc == WS_CHANNEL_CLOSED) {
peerConnected = 0;
continue;
}
else if (rc == WS_WANT_WRITE) {
windowFull = 1;
continue;
}
else if (rc != WS_WANT_READ) {
Expand All @@ -1468,7 +1482,10 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
shellBuffer, cnt_r);
if (cnt_w == WS_WINDOW_FULL) {
windowFull = 1;
idle = 0;
continue;
}
else if (cnt_w == WS_WANT_WRITE) {
windowFull = 1;
continue;
}
else {
Expand All @@ -1489,13 +1506,16 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}
else {
if (cnt_r > 0) {
idle = 0;
cnt_w = wolfSSH_extended_data_send(ssh, shellBuffer,
cnt_r);
if (cnt_w == WS_WINDOW_FULL) {
windowFull = 1;
continue;
}
else if (cnt_w == WS_WANT_WRITE) {
windowFull = 1;
continue;
}
else if (cnt_w < 0)
break;
}
Expand All @@ -1507,23 +1527,31 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
cnt_r = (int)read(stdoutPipe[0], shellBuffer,
sizeof shellBuffer);
/* This read will return 0 on EOF */
if (cnt_r <= 0) {
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) {
idle = 0;
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, cnt_r);
if (cnt_w == WS_WINDOW_FULL) {
windowFull = 1;
continue;
}
else if (cnt_w < 0)
else if (cnt_w == WS_WANT_WRITE) {
windowFull = 1;
continue;
}
else if (cnt_w < 0) {
kill(childPid, SIGINT);
break;
}
}
}
}
Expand All @@ -1540,22 +1568,27 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
}
else {
if (cnt_r > 0) {
idle = 0;
cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId,
shellBuffer, cnt_r);
if (cnt_w == WS_WINDOW_FULL) {
windowFull = 1;
continue;
}
else if (cnt_w < 0)
else if (cnt_w == WS_WANT_WRITE) {
windowFull = 1;
continue;
}
else if (cnt_w < 0) {
kill(childPid, SIGINT);
break;
}
}
}
}
}

if (ChildRunning && idle) {
idle = 0; /* waiting on child process */
if (!ChildRunning && peerConnected && stdoutEmpty && !windowFull) {
peerConnected = 0;
}
}

Expand Down Expand Up @@ -1868,7 +1901,7 @@ static void* HandleConnection(void* arg)
#ifdef _WIN32
Sleep(1);
#else
usleep(1);
usleep(100000);
#endif
}

Expand All @@ -1882,6 +1915,13 @@ static void* HandleConnection(void* arg)
/* check if there is a response to the shutdown */
wolfSSH_free(ssh);
if (conn != NULL) {
byte sc[1024];
shutdown(conn->fd, 1);
/* Spin until socket closes. */
do {
ret = (int)recv(conn->fd, sc, 1024, 0);
} while (ret > 0);

WCLOSESOCKET(conn->fd);
}
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Return from closing connection = %d", ret);
Expand Down Expand Up @@ -2037,7 +2077,7 @@ static char* _convertHelper(WCHAR* in, void* heap) {
if (ret != NULL) {
size_t numConv = 0;
if (wcstombs_s(&numConv, ret, retSz, in, retSz) != 0) {
XFREE(ret, heap, DYNTYPE_SSHD);
WFREE(ret, heap, DYNTYPE_SSHD);
ret = NULL;
}
}
Expand Down

0 comments on commit e3bed88

Please sign in to comment.