Reject a window-change on a channel with no pty

A window-change arriving before any pty-req had nothing to resize, but
the size was stored and the resize callback run anyway. Dropbear refuses
the same request for the same reason.

- Reject it with the existing rej path, so no reply is sent for a
  request RFC 4254 sec 6.7 says takes none, and the session continues.
- unit.c covers the rejection, and now drives a real pty-req, which
  had no coverage on the receive side at all.
pull/1171/head
John Safranek 2026-08-17 18:38:32 -07:00 committed by philljj
parent f956512c5a
commit e6bce999c6
2 changed files with 79 additions and 3 deletions

View File

@ -11714,7 +11714,6 @@ static int DoChannelRequest(WOLFSSH* ssh,
word32 termSz;
word32 widthChar, heightRows, widthPixels, heightPixels;
channel->ptyReq = 1; /* received a pty request */
termSz = (word32)sizeof(term);
ret = GetString(term, &termSz, buf, len, &begin);
if (ret == WS_SUCCESS)
@ -11730,6 +11729,7 @@ static int DoChannelRequest(WOLFSSH* ssh,
(char**)&ssh->modes, &ssh->modesSz,
buf, len, &begin);
if (ret == WS_SUCCESS) {
channel->ptyReq = 1; /* only on a fully parsed request */
SetTerminalSize(ssh, widthChar, heightRows,
widthPixels, heightPixels);
WLOG(WS_LOG_DEBUG, " term = %s", term);
@ -11762,7 +11762,13 @@ static int DoChannelRequest(WOLFSSH* ssh,
if (ret == WS_SUCCESS)
ret = GetUint32(&heightPixels, buf, len, &begin);
if (ret == WS_SUCCESS) {
if (ret == WS_SUCCESS && !channel->ptyReq) {
/* Nothing to resize without a pty on this channel. Dropbear
* refuses the same request for the same reason. */
WLOG(WS_LOG_DEBUG, " no pty on this channel, rejecting.");
rej = 1;
}
else if (ret == WS_SUCCESS) {
SetTerminalSize(ssh, widthChar, heightRows,
widthPixels, heightPixels);
WLOG(WS_LOG_DEBUG, " widthChar = %u", ssh->widthChar);

View File

@ -7021,7 +7021,8 @@ static int test_DoChannelRequest(void)
#endif /* WOLFSSH_TERM || WOLFSSH_SHELL */
/* RFC 4254 sec 6.7: window-change must not send a reply even if the
* wire wantReply byte is 1. */
* wire wantReply byte is 1. No pty-req has been seen on this channel
* yet, so the request is also rejected and the size stays put. */
#if defined(WOLFSSH_SHELL) && defined(WOLFSSH_TERM)
{
static const byte payWindowChange[] = {
@ -7055,6 +7056,75 @@ static int test_DoChannelRequest(void)
result = -451;
goto done;
}
if (ssh->widthChar != 0 || ssh->heightRows != 0) {
printf("DoChannelRequest[window-change]: applied %ux%u without "
"a pty\n", ssh->widthChar, ssh->heightRows);
result = -452;
goto done;
}
}
/* A pty-req establishes the pty and the size, and runs the same
* clamping the window-change branch does. */
{
static byte payPtyReq[] = {
0x00,0x00,0x00,0x00, /* channelId = 0 */
0x00,0x00,0x00,0x07, /* typeSz = 7 */
0x70,0x74,0x79,0x2D,0x72,0x65,0x71, /* "pty-req" */
0x00, /* wantReply = 0 */
0x00,0x00,0x00,0x05, /* termSz = 5 */
0x76,0x74,0x31,0x30,0x30, /* "vt100" */
0x00,0x00,0x00,0x50, /* widthChar = 80 */
0x00,0x00,0x00,0x18, /* heightRows = 24 */
0x00,0x00,0x02,0x80, /* widthPixels = 640 */
0x00,0x00,0x01,0xE0, /* heightPixels = 480 */
0x00,0x00,0x00,0x01, /* modesSz = 1 */
0x00 /* TTY_OP_END */
};
/* offsets of the four dimensions within the payload above */
const word32 pwcOff = 25, phrOff = 29, pwpOff = 33, phpOff = 37;
word32 idx2 = 0;
int ret2;
ret2 = wolfSSH_TestDoChannelRequest(ssh, payPtyReq,
(word32)sizeof(payPtyReq), &idx2);
if (ret2 != WS_SUCCESS) {
printf("DoChannelRequest[pty-req]: ret=%d, expected=%d\n",
ret2, WS_SUCCESS);
result = -453;
goto done;
}
if (ssh->widthChar != 80 || ssh->heightRows != 24 ||
ssh->widthPixels != 640 || ssh->heightPixels != 480) {
printf("DoChannelRequest[pty-req]: got %ux%u %ux%u, "
"expected 80x24 640x480\n", ssh->widthChar,
ssh->heightRows, ssh->widthPixels, ssh->heightPixels);
result = -454;
goto done;
}
/* the clamp is on the pty-req path too, pixels included */
PutU32BE(payPtyReq + pwcOff, 0x10000);
PutU32BE(payPtyReq + phrOff, 0x10000);
PutU32BE(payPtyReq + pwpOff, 0xFFFFFFFF);
PutU32BE(payPtyReq + phpOff, 0xFFFFFFFF);
idx2 = 0;
ret2 = wolfSSH_TestDoChannelRequest(ssh, payPtyReq,
(word32)sizeof(payPtyReq), &idx2);
if (ret2 != WS_SUCCESS) {
printf("DoChannelRequest[pty-req clamp]: ret=%d, expected=%d\n",
ret2, WS_SUCCESS);
result = -455;
goto done;
}
if (ssh->widthChar != 65535 || ssh->heightRows != 65535 ||
ssh->widthPixels != 65535 || ssh->heightPixels != 65535) {
printf("DoChannelRequest[pty-req clamp]: got %ux%u %ux%u, "
"expected 65535 throughout\n", ssh->widthChar,
ssh->heightRows, ssh->widthPixels, ssh->heightPixels);
result = -456;
goto done;
}
}
/* Dimensions are stored as sent, zero included, as others do.