From 6fe09bdb35ac5ceac67ca59eb71ed933030f186a Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 16 Sep 2025 10:11:46 -0600 Subject: [PATCH] do not treat shell as interactive until pty-req received --- apps/wolfsshd/wolfsshd.c | 27 ++++++++++++++++++--------- src/internal.c | 1 + src/ssh.c | 19 +++++++++++++++++++ wolfssh/internal.h | 1 + wolfssh/ssh.h | 1 + 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index de6b14da..bb759842 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1193,6 +1193,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, int wantWrite = 0; int peerConnected = 1; int stdoutEmpty = 0; + int ptyReq = 0; childFd = -1; stdoutPipe[0] = -1; @@ -1203,6 +1204,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, stdinPipe[1] = -1; forcedCmd = wolfSSHD_ConfigGetForcedCmd(usrConf); + ptyReq = wolfSSH_ReceivedPtyReq(ssh); /* do not overwrite a forced command with 'exec' sub shell. Only set the * 'exec' command when no forced command is set */ @@ -1223,8 +1225,9 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, return WS_FATAL_ERROR; } + /* create pipes for stdout and stderr */ - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { if (pipe(stdoutPipe) != 0) { wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue creating stdout pipe"); return WS_FATAL_ERROR; @@ -1263,7 +1266,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, signal(SIGINT, SIG_DFL); signal(SIGCHLD, SIG_DFL); - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { close(stdoutPipe[0]); close(stderrPipe[0]); close(stdinPipe[1]); @@ -1390,7 +1393,13 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, close(stderrPipe[1]); close(stdinPipe[1]); } - else { + else if (ptyReq == 0) { + ret = execv(cmd, (char**)args); + close(stdoutPipe[1]); + close(stderrPipe[1]); + close(stdinPipe[1]); + } + else { /* open interactive shell */ ret = execv(cmd, (char**)args); } if (ret && errno) { @@ -1443,7 +1452,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, #endif wolfSSH_SetTerminalResizeCtx(ssh, (void*)&childFd); - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { close(stdoutPipe[1]); close(stderrPipe[1]); close(stdinPipe[0]); @@ -1469,7 +1478,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, if (wolfSSH_stream_peek(ssh, tmp, 1) <= 0) { /* select on stdout/stderr pipes with forced commands */ - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { FD_SET(stdoutPipe[0], &readFds); if (stdoutPipe[0] > maxFd) maxFd = stdoutPipe[0]; @@ -1515,7 +1524,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, if (cnt_r <= 0) break; - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { cnt_w = (int)write(stdinPipe[1], channelBuffer, cnt_r); } @@ -1555,7 +1564,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, current = wolfSSH_ChannelFind(ssh, lastChannel, WS_CHANNEL_ID_SELF); eof = wolfSSH_ChannelGetEof(current); - if (eof && forcedCmd) { + if (eof && (ptyReq == 0 || forcedCmd)) { /* SSH is done, close stdin pipe to child process */ close(stdinPipe[1]); stdinPipe[1] = -1; @@ -1585,7 +1594,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } } - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { if (FD_ISSET(stderrPipe[0], &readFds)) { cnt_r = (int)read(stderrPipe[0], shellBuffer, sizeof shellBuffer); @@ -1725,7 +1734,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh, } /* check for any left over data in pipes then close them */ - if (forcedCmd) { + if (ptyReq == 0 || forcedCmd) { int readSz; fcntl(stdoutPipe[0], F_SETFL, fcntl(stdoutPipe[0], F_GETFL) diff --git a/src/internal.c b/src/internal.c index 63f0e1af..9c98e42b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8951,6 +8951,7 @@ static int DoChannelRequest(WOLFSSH* ssh, word32 termSz, modesSz = 0; word32 widthChar, heightRows, widthPixels, heightPixels; + ssh->ptyReq = 1; /* recieved a pty request */ termSz = (word32)sizeof(term); ret = GetString(term, &termSz, buf, len, &begin); if (ret == WS_SUCCESS) diff --git a/src/ssh.c b/src/ssh.c index f98fb302..777247c4 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -2539,6 +2539,25 @@ WS_SessionType wolfSSH_GetSessionType(const WOLFSSH* ssh) } +#if defined(WOLFSSH_TERM) +int wolfSSH_ReceivedPtyReq(const WOLFSSH* ssh) +{ + WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ReceivedPtyReq"); + + if (ssh == NULL) { + return WS_BAD_ARGUMENT; + } + + if (ssh->ptyReq) { + return 1; + } + else { + return 0; + } +} +#endif + + const char* wolfSSH_GetSessionCommand(const WOLFSSH* ssh) { WLOG(WS_LOG_DEBUG, "Entering wolfSSH_GetSessionCommand()"); diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 261ae6d4..52175c68 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -913,6 +913,7 @@ struct WOLFSSH { word32 heightPixels; /* pixel height */ byte* modes; word32 modesSz; + byte ptyReq:1; /* flag for if interactive pty request was received */ #endif #if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) word32 exitStatus; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index ccdfda47..6ce71b5a 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -233,6 +233,7 @@ WOLFSSH_API WS_SessionType wolfSSH_ChannelGetSessionType( const WOLFSSH_CHANNEL* channel); WOLFSSH_API const char* wolfSSH_ChannelGetSessionCommand( const WOLFSSH_CHANNEL* channel); +WOLFSSH_API int wolfSSH_ReceivedPtyReq(const WOLFSSH* ssh); /* Channel callbacks */ typedef int (*WS_CallbackChannelOpen)(WOLFSSH_CHANNEL* channel, void* ctx);