mirror of https://github.com/wolfSSL/wolfssh.git
add piping of stderr
parent
dce3cf09e9
commit
b711d62238
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
109
src/internal.c
109
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)
|
||||
{
|
||||
|
|
21
src/ssh.c
21
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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue