add piping of stderr

pull/615/head
JacobBarthelmeh 2023-11-05 22:39:02 -08:00
parent dce3cf09e9
commit b711d62238
6 changed files with 210 additions and 5 deletions

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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 */

View File

@ -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,

View File

@ -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);