mirror of https://github.com/wolfSSL/wolfssh.git
internal: bare success for a fixed-port forward
RFC 4254 7.1 gives a tcpip-forward success a trailing bound-port field only for a port-0 (dynamic) request. DoGlobalRequestFwd() now sends that field only when the peer asked the server to allocate a port, and answers an explicit port with a bare SSH_MSG_REQUEST_SUCCESS, as OpenSSH and libssh do. - Key the reply builder off requestedPort, which the port-0 compliance check already tracks. - Check the reply payload length against the requested port in the regress global-request helper, which had baked in the trailing field. - Add ParseGlobalRequestFwdBindPort() to recover that port from the request the harness fed in. - Cover the explicit-port reply. Issue: #1246pull/1254/head
parent
ba8996038d
commit
02ecaa015e
|
|
@ -12164,11 +12164,14 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh,
|
|||
|
||||
if (wantReply) {
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (isCancel) {
|
||||
ret = SendRequestSuccess(ssh, 1);
|
||||
/* RFC 4254 7.1 gives the success a trailing bound-port field only
|
||||
* for a port-0 (dynamic) request. An explicit port, and a cancel,
|
||||
* get a bare success with no response-specific data. */
|
||||
if (!isCancel && requestedPort == 0) {
|
||||
ret = SendGlobalRequestFwdSuccess(ssh, 1, bindPort);
|
||||
}
|
||||
else {
|
||||
ret = SendGlobalRequestFwdSuccess(ssh, 1, bindPort);
|
||||
ret = SendRequestSuccess(ssh, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -2151,6 +2151,37 @@ static const byte* ParseGlobalRequestName(const byte* packet, word32 packetSz,
|
|||
return payload + 1 + sizeof(word32);
|
||||
}
|
||||
|
||||
/* Bind port of a tcpip-forward global request. Past the request name and the
|
||||
* want-reply byte come the bind address and then the port. */
|
||||
static word32 ParseGlobalRequestFwdBindPort(const byte* packet,
|
||||
word32 packetSz)
|
||||
{
|
||||
const byte* payload;
|
||||
const byte* reqName;
|
||||
word32 reqNameSz;
|
||||
word32 payloadLen;
|
||||
word32 idx;
|
||||
word32 strSz;
|
||||
word32 port;
|
||||
|
||||
reqName = ParseGlobalRequestName(packet, packetSz, &reqNameSz);
|
||||
payload = packet + 5;
|
||||
payloadLen = ParsePayloadLen(packet, packetSz);
|
||||
idx = (word32)(reqName - payload) + reqNameSz;
|
||||
|
||||
AssertTrue(payloadLen >= idx + 1 + sizeof(word32));
|
||||
idx += 1;
|
||||
|
||||
WMEMCPY(&strSz, payload + idx, sizeof(strSz));
|
||||
strSz = ntohl(strSz);
|
||||
idx += (word32)sizeof(word32) + strSz;
|
||||
|
||||
AssertTrue(payloadLen >= idx + sizeof(word32));
|
||||
WMEMCPY(&port, payload + idx, sizeof(port));
|
||||
|
||||
return ntohl(port);
|
||||
}
|
||||
|
||||
static void AssertGlobalRequestReply(const ChannelOpenHarness* harness,
|
||||
byte expectedMsgId)
|
||||
{
|
||||
|
|
@ -2175,7 +2206,14 @@ static void AssertGlobalRequestReply(const ChannelOpenHarness* harness,
|
|||
if (reqNameSz == sizeof("tcpip-forward") - 1 &&
|
||||
WMEMCMP(reqName, "tcpip-forward",
|
||||
sizeof("tcpip-forward") - 1) == 0) {
|
||||
AssertIntEQ(payloadLen, 5);
|
||||
/* The bound port trails the success only for a port-0 request. */
|
||||
if (ParseGlobalRequestFwdBindPort(harness->io.in,
|
||||
harness->io.inSz) == 0) {
|
||||
AssertIntEQ(payloadLen, 5);
|
||||
}
|
||||
else {
|
||||
AssertIntEQ(payloadLen, 1);
|
||||
}
|
||||
}
|
||||
else if (reqNameSz == sizeof("cancel-tcpip-forward") - 1 &&
|
||||
WMEMCMP(reqName, "cancel-tcpip-forward",
|
||||
|
|
@ -5583,6 +5621,30 @@ static void TestGlobalRequestFwdPort0ReturnsAllocatedPort(void)
|
|||
FreeChannelOpenHarness(&harness);
|
||||
}
|
||||
|
||||
/* RFC 4254 7.1 defines the trailing bound-port field only for a port-0
|
||||
* request. An explicit port must be answered with a bare success. */
|
||||
static void TestGlobalRequestFwdExplicitPortReplyHasNoPort(void)
|
||||
{
|
||||
ChannelOpenHarness harness;
|
||||
byte in[256];
|
||||
word32 inSz;
|
||||
int ret;
|
||||
|
||||
inSz = BuildGlobalRequestFwdPacket("0.0.0.0", 8022, 0, 1, in, sizeof(in));
|
||||
InitChannelOpenHarness(&harness, in, inSz);
|
||||
AssertIntEQ(wolfSSH_CTX_SetFwdCb(harness.ctx, AcceptFwdCb, NULL),
|
||||
WS_SUCCESS);
|
||||
|
||||
ret = DoReceive(harness.ssh);
|
||||
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertIntEQ(ParseMsgId(harness.io.out, harness.io.outSz),
|
||||
MSGID_REQUEST_SUCCESS);
|
||||
AssertIntEQ(ParsePayloadLen(harness.io.out, harness.io.outSz), 1);
|
||||
|
||||
FreeChannelOpenHarness(&harness);
|
||||
}
|
||||
|
||||
static void TestGlobalRequestFwdPort0NoAllocSendsFailure(void)
|
||||
{
|
||||
ChannelOpenHarness harness;
|
||||
|
|
@ -14955,6 +15017,7 @@ int main(int argc, char** argv)
|
|||
TestGlobalRequestFwdNoCbNoReplyKeepsConnection();
|
||||
TestGlobalRequestFwdWithCbSendsSuccess();
|
||||
TestGlobalRequestFwdPort0ReturnsAllocatedPort();
|
||||
TestGlobalRequestFwdExplicitPortReplyHasNoPort();
|
||||
TestGlobalRequestFwdPort0NoAllocSendsFailure();
|
||||
TestGlobalRequestFwdRemoteSetupErrorSendsFailure();
|
||||
TestGlobalRequestFwdPort0NoAllocNoReplyKeepsConnection();
|
||||
|
|
|
|||
Loading…
Reference in New Issue