Add restricted wolfSSH ordering fix
Apply hash-pinned generated edits for CVE-2025-14942 while keeping wolfSSH 1.4.20 managed sources unchanged. Add the ABI header overlay, provenance records, and real state-machine interoperability contracts.
This commit is contained in:
@@ -0,0 +1,882 @@
|
||||
From 5fa6c0fce30a421879b355a007ef843eb48332d3 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Thu, 27 Mar 2025 08:54:23 -0600
|
||||
Subject: [PATCH 1/8] sanity checks on message types during rekey
|
||||
|
||||
---
|
||||
src/internal.c | 55 +++++++++++++++++++++++++++++++++++++++++++---
|
||||
wolfssh/internal.h | 5 ++++-
|
||||
2 files changed, 56 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index 63f0e1af7..739a9bad2 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -595,6 +595,40 @@ static void HandshakeInfoFree(HandshakeInfo* hs, void* heap)
|
||||
}
|
||||
|
||||
|
||||
+/* RFC 4253 section 7.1, Once having sent SSH_MSG_KEXINIT the only messages
|
||||
+* that can be sent are 1-19 (except SSH_MSG_SERVICE_REQUEST and
|
||||
+* SSH_MSG_SERVICE_ACCEPT), 20-29 (except SSH_MSG_KEXINIT again), and 30-49
|
||||
+*/
|
||||
+INLINE static int IsMessageAllowedKeying(WOLFSSH *ssh, byte msg)
|
||||
+{
|
||||
+ if (ssh->isKeying == 0) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /* case of servie request or accept in 1-19 */
|
||||
+ if (msg == MSGID_SERVICE_REQUEST || msg == MSGID_SERVICE_ACCEPT) {
|
||||
+ WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by during rekeying", msg);
|
||||
+ ssh->error = WS_REKEYING;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* case of resending SSH_MSG_KEXINIT */
|
||||
+ if (msg == MSGID_KEXINIT) {
|
||||
+ WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by during rekeying", msg);
|
||||
+ ssh->error = WS_REKEYING;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* case where message id greater than 49 */
|
||||
+ if (msg >= MSGID_USERAUTH_REQUEST) {
|
||||
+ WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by during rekeying", msg);
|
||||
+ ssh->error = WS_REKEYING;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
#ifndef NO_WOLFSSH_SERVER
|
||||
INLINE static int IsMessageAllowedServer(WOLFSSH *ssh, byte msg)
|
||||
{
|
||||
@@ -673,8 +707,12 @@ INLINE static int IsMessageAllowedClient(WOLFSSH *ssh, byte msg)
|
||||
#endif /* NO_WOLFSSH_CLIENT */
|
||||
|
||||
|
||||
-INLINE static int IsMessageAllowed(WOLFSSH *ssh, byte msg)
|
||||
+INLINE static int IsMessageAllowed(WOLFSSH *ssh, byte msg, byte state)
|
||||
{
|
||||
+ if (state == WS_MSG_SEND && !IsMessageAllowedKeying(ssh, msg)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
#ifndef NO_WOLFSSH_SERVER
|
||||
if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {
|
||||
return IsMessageAllowedServer(ssh, msg);
|
||||
@@ -5905,7 +5943,6 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
HandshakeInfoFree(ssh->handshake, ssh->ctx->heap);
|
||||
ssh->handshake = NULL;
|
||||
WLOG(WS_LOG_DEBUG, "Keying completed");
|
||||
-
|
||||
if (ssh->ctx->keyingCompletionCb)
|
||||
ssh->ctx->keyingCompletionCb(ssh->keyingCompletionCtx);
|
||||
}
|
||||
@@ -9309,7 +9346,7 @@ static int DoPacket(WOLFSSH* ssh, byte* bufferConsumed)
|
||||
return WS_OVERFLOW_E;
|
||||
}
|
||||
|
||||
- if (!IsMessageAllowed(ssh, msg)) {
|
||||
+ if (!IsMessageAllowed(ssh, msg, WS_MSG_RECV)) {
|
||||
return WS_MSGID_NOT_ALLOWED_E;
|
||||
}
|
||||
|
||||
@@ -15649,6 +15686,12 @@ int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId)
|
||||
if (ssh == NULL)
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
|
||||
+ if (ret == WS_SUCCESS) {
|
||||
+ if (!IsMessageAllowed(ssh, MSGID_CHANNEL_EOF, WS_MSG_SEND)) {
|
||||
+ ret = WS_MSGID_NOT_ALLOWED_E;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (ret == WS_SUCCESS) {
|
||||
channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);
|
||||
if (channel == NULL)
|
||||
@@ -16077,6 +16120,12 @@ int SendChannelWindowAdjust(WOLFSSH* ssh, word32 channelId,
|
||||
if (ssh == NULL)
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
|
||||
+ if (ret == WS_SUCCESS) {
|
||||
+ if (!IsMessageAllowed(ssh, MSGID_CHANNEL_WINDOW_ADJUST, WS_MSG_SEND)) {
|
||||
+ ret = WS_MSGID_NOT_ALLOWED_E;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
|
||||
if (channel == NULL) {
|
||||
WLOG(WS_LOG_DEBUG, "Invalid channel");
|
||||
diff --git a/wolfssh/internal.h b/wolfssh/internal.h
|
||||
index 261ae6d42..29a6f8ef8 100644
|
||||
--- a/wolfssh/internal.h
|
||||
+++ b/wolfssh/internal.h
|
||||
@@ -1249,6 +1249,10 @@ enum WS_MessageIds {
|
||||
|
||||
#define CHANNEL_EXTENDED_DATA_STDERR WOLFSSH_EXT_DATA_STDERR
|
||||
|
||||
+/* Used when checking IsMessageAllowed() to determine if createing and sending
|
||||
+ * the message or receiving the message is allowed */
|
||||
+#define WS_MSG_SEND 1
|
||||
+#define WS_MSG_RECV 2
|
||||
|
||||
/* dynamic memory types */
|
||||
enum WS_DynamicTypes {
|
||||
@@ -1442,4 +1446,3 @@ enum TerminalModes {
|
||||
#endif
|
||||
|
||||
#endif /* _WOLFSSH_INTERNAL_H_ */
|
||||
-
|
||||
|
||||
From af45bc3719ddeac112d9d70b2e6a969f1aa3f3e7 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Tue, 13 May 2025 16:01:01 -0600
|
||||
Subject: [PATCH 2/8] update example client for rekey and sanity check on
|
||||
window update after read attempt
|
||||
|
||||
---
|
||||
examples/client/client.c | 11 +++++++++++
|
||||
src/ssh.c | 12 +++++++++++-
|
||||
2 files changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/examples/client/client.c b/examples/client/client.c
|
||||
index e27305f72..f415bd801 100644
|
||||
--- a/examples/client/client.c
|
||||
+++ b/examples/client/client.c
|
||||
@@ -342,6 +342,9 @@ static THREAD_RET readInput(void* in)
|
||||
ret = wolfSSH_stream_send(args->ssh, buf, sz);
|
||||
wc_UnLockMutex(&args->lock);
|
||||
if (ret <= 0) {
|
||||
+ if (ret == WS_REKEYING) {
|
||||
+ continue;
|
||||
+ }
|
||||
fprintf(stderr, "Couldn't send data\n");
|
||||
return THREAD_RET_SUCCESS;
|
||||
}
|
||||
@@ -472,8 +475,16 @@ static THREAD_RET readPeer(void* in)
|
||||
continue;
|
||||
}
|
||||
#endif /* WOLFSSH_AGENT */
|
||||
+ else if (ret == WS_REKEYING) {
|
||||
+ wolfSSH_worker(args->ssh, NULL);
|
||||
+ ret = 0;
|
||||
+ }
|
||||
}
|
||||
else if (ret != WS_EOF) {
|
||||
+ if (ret == 0) {
|
||||
+ bytes = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
err_sys("Stream read failed.");
|
||||
}
|
||||
}
|
||||
diff --git a/src/ssh.c b/src/ssh.c
|
||||
index 05c1a7b3e..2ed75d1bc 100644
|
||||
--- a/src/ssh.c
|
||||
+++ b/src/ssh.c
|
||||
@@ -1135,6 +1135,11 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
||||
return WS_ERROR;
|
||||
}
|
||||
|
||||
+ if (ssh->isKeying) {
|
||||
+ ssh->error = WS_REKEYING;
|
||||
+ return WS_FATAL_ERROR;
|
||||
+ }
|
||||
+
|
||||
inputBuffer = &ssh->channelList->inputBuffer;
|
||||
ssh->error = WS_SUCCESS;
|
||||
|
||||
@@ -1164,7 +1169,7 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
||||
}
|
||||
|
||||
/* update internal input buffer based on data read */
|
||||
- if (ret == WS_SUCCESS) {
|
||||
+ if (ret == WS_SUCCESS && !ssh->isKeying) {
|
||||
int n;
|
||||
|
||||
n = min(bufSz, inputBuffer->length - inputBuffer->idx);
|
||||
@@ -2901,6 +2906,11 @@ int wolfSSH_ChannelRead(WOLFSSH_CHANNEL* channel, byte* buf, word32 bufSz)
|
||||
if (channel == NULL || buf == NULL || bufSz == 0)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
+ if (channel->ssh->isKeying) {
|
||||
+ channel->ssh->error = WS_REKEYING;
|
||||
+ return WS_REKEYING;
|
||||
+ }
|
||||
+
|
||||
bufSz = _ChannelRead(channel, buf, bufSz);
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelRead(), bytesRxd = %d",
|
||||
|
||||
From d74c942c84d44fb46d3a10cb56233b704733e466 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Thu, 15 May 2025 11:38:45 -0600
|
||||
Subject: [PATCH 3/8] refactor SFTP to use NoticeError
|
||||
|
||||
---
|
||||
examples/sftpclient/sftpclient.c | 8 +++++++-
|
||||
src/ssh.c | 2 +-
|
||||
src/wolfsftp.c | 25 +++++++++++--------------
|
||||
3 files changed, 19 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c
|
||||
index 779baff1f..a990bc14e 100644
|
||||
--- a/examples/sftpclient/sftpclient.c
|
||||
+++ b/examples/sftpclient/sftpclient.c
|
||||
@@ -1119,7 +1119,7 @@ static int doCmds(func_args* args)
|
||||
/* alternate main loop for the autopilot get/receive */
|
||||
static int doAutopilot(int cmd, char* local, char* remote)
|
||||
{
|
||||
- int err;
|
||||
+ int err = 0;
|
||||
int ret = WS_SUCCESS;
|
||||
char fullpath[128] = ".";
|
||||
WS_SFTPNAME* name = NULL;
|
||||
@@ -1156,6 +1156,12 @@ static int doAutopilot(int cmd, char* local, char* remote)
|
||||
}
|
||||
|
||||
do {
|
||||
+ if (err == WS_REKEYING) { /* handle rekeying state */
|
||||
+ do {
|
||||
+ ret = wolfSSH_worker(ssh, NULL);
|
||||
+ } while (ret == WS_REKEYING);
|
||||
+ }
|
||||
+
|
||||
if (cmd == AUTOPILOT_PUT) {
|
||||
ret = wolfSSH_SFTP_Put(ssh, local, fullpath, 0, NULL);
|
||||
}
|
||||
diff --git a/src/ssh.c b/src/ssh.c
|
||||
index 2ed75d1bc..56c248589 100644
|
||||
--- a/src/ssh.c
|
||||
+++ b/src/ssh.c
|
||||
@@ -1201,7 +1201,7 @@ int wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
||||
|
||||
if (ssh->isKeying) {
|
||||
ssh->error = WS_REKEYING;
|
||||
- return WS_REKEYING;
|
||||
+ return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
bytesTxd = SendChannelData(ssh, ssh->channelList->channel, buf, bufSz);
|
||||
diff --git a/src/wolfsftp.c b/src/wolfsftp.c
|
||||
index 761830a34..a95428fd0 100644
|
||||
--- a/src/wolfsftp.c
|
||||
+++ b/src/wolfsftp.c
|
||||
@@ -1418,7 +1418,11 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
|
||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||
state->buffer.sz);
|
||||
if (ret < 0) {
|
||||
- if (!NoticeError(ssh)) {
|
||||
+ if (NoticeError(ssh)) {
|
||||
+ /* keep state for returning to */
|
||||
+ ret = WS_FATAL_ERROR;
|
||||
+ }
|
||||
+ else {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV);
|
||||
}
|
||||
return ret;
|
||||
@@ -7452,8 +7456,7 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
/* send header and type specific data */
|
||||
ret = wolfSSH_SFTP_buffer_send(ssh, &state->buffer);
|
||||
if (ret < 0) {
|
||||
- if (ssh->error == WS_WANT_READ ||
|
||||
- ssh->error == WS_WANT_WRITE) {
|
||||
+ if (NoticeError(ssh)) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
state->state = STATE_SEND_WRITE_CLEANUP;
|
||||
@@ -7465,12 +7468,8 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
case STATE_SEND_WRITE_SEND_BODY:
|
||||
WLOG(WS_LOG_SFTP, "SFTP SEND_WRITE STATE: SEND_BODY");
|
||||
state->sentSz = wolfSSH_stream_send(ssh, in, inSz);
|
||||
- if (state->sentSz == WS_WINDOW_FULL ||
|
||||
- state->sentSz == WS_REKEYING ||
|
||||
- state->sentSz == WS_WANT_READ ||
|
||||
- state->sentSz == WS_WANT_WRITE) {
|
||||
- ret = wolfSSH_worker(ssh, NULL);
|
||||
- continue; /* skip past rest and send more */
|
||||
+ if (NoticeError(ssh)) {
|
||||
+ return WS_FATAL_ERROR;
|
||||
}
|
||||
if (state->sentSz <= 0) {
|
||||
ssh->error = state->sentSz;
|
||||
@@ -7496,8 +7495,7 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
state->maxSz = SFTP_GetHeader(ssh, &state->reqId, &type,
|
||||
&state->buffer);
|
||||
if (state->maxSz <= 0) {
|
||||
- if (ssh->error == WS_WANT_READ ||
|
||||
- ssh->error == WS_WANT_WRITE) {
|
||||
+ if (NoticeError(ssh)) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
ssh->error = WS_SFTP_BAD_HEADER;
|
||||
@@ -9167,10 +9165,9 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
||||
state->handle, state->handleSz, state->pOfst,
|
||||
state->r, state->rSz);
|
||||
if (sz <= 0) {
|
||||
- if (ssh->error == WS_WANT_READ ||
|
||||
- ssh->error == WS_WANT_WRITE ||
|
||||
- ssh->error == WS_WINDOW_FULL)
|
||||
+ if (NoticeError(ssh)) {
|
||||
return WS_FATAL_ERROR;
|
||||
+ }
|
||||
}
|
||||
else {
|
||||
AddAssign64(state->pOfst, sz);
|
||||
|
||||
From ff95f3c3029d766b114a91d98b013e0a1636a6c1 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Thu, 15 May 2025 13:32:33 -0600
|
||||
Subject: [PATCH 4/8] increase timeout time on test, fix spelling, add comment
|
||||
on new arg
|
||||
|
||||
---
|
||||
.github/workflows/sshd-test.yml | 2 +-
|
||||
src/internal.c | 2 ++
|
||||
wolfssh/internal.h | 2 +-
|
||||
3 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/.github/workflows/sshd-test.yml b/.github/workflows/sshd-test.yml
|
||||
index 3fbe3daf8..eb075a6f1 100644
|
||||
--- a/.github/workflows/sshd-test.yml
|
||||
+++ b/.github/workflows/sshd-test.yml
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
wolfssl: ${{ fromJson(needs.create_matrix.outputs['versions']) }}
|
||||
name: Build and test wolfsshd
|
||||
runs-on: ${{ matrix.os }}
|
||||
- timeout-minutes: 10
|
||||
+ timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checking cache for wolfssl
|
||||
uses: actions/cache@v4
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index 739a9bad2..ff912ef74 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -707,6 +707,8 @@ INLINE static int IsMessageAllowedClient(WOLFSSH *ssh, byte msg)
|
||||
#endif /* NO_WOLFSSH_CLIENT */
|
||||
|
||||
|
||||
+/* 'state' argument is for if trying to send a message or receive one.
|
||||
+ * Returns 1 if allowed 0 if not allowed. */
|
||||
INLINE static int IsMessageAllowed(WOLFSSH *ssh, byte msg, byte state)
|
||||
{
|
||||
if (state == WS_MSG_SEND && !IsMessageAllowedKeying(ssh, msg)) {
|
||||
diff --git a/wolfssh/internal.h b/wolfssh/internal.h
|
||||
index 29a6f8ef8..ad5e00b0e 100644
|
||||
--- a/wolfssh/internal.h
|
||||
+++ b/wolfssh/internal.h
|
||||
@@ -1249,7 +1249,7 @@ enum WS_MessageIds {
|
||||
|
||||
#define CHANNEL_EXTENDED_DATA_STDERR WOLFSSH_EXT_DATA_STDERR
|
||||
|
||||
-/* Used when checking IsMessageAllowed() to determine if createing and sending
|
||||
+/* Used when checking IsMessageAllowed() to determine if creating and sending
|
||||
* the message or receiving the message is allowed */
|
||||
#define WS_MSG_SEND 1
|
||||
#define WS_MSG_RECV 2
|
||||
|
||||
From 2a11471bb717a2ee6f06b3e1beab8a3e2b0ef261 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Tue, 16 Sep 2025 13:30:25 -0600
|
||||
Subject: [PATCH 5/8] refactor introducing more use of NoticeError
|
||||
|
||||
---
|
||||
examples/echoserver/echoserver.c | 5 +-
|
||||
examples/sftpclient/sftpclient.c | 81 ++++++++++++++++++++++++++++----
|
||||
src/wolfsftp.c | 35 +++++++-------
|
||||
tests/api.c | 5 ++
|
||||
4 files changed, 100 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c
|
||||
index 1fbd58a0c..8d14a7c95 100644
|
||||
--- a/examples/echoserver/echoserver.c
|
||||
+++ b/examples/echoserver/echoserver.c
|
||||
@@ -1416,8 +1416,11 @@ static int sftp_worker(thread_ctx_t* threadCtx)
|
||||
}
|
||||
else if (ret < 0) {
|
||||
error = wolfSSH_get_error(ssh);
|
||||
- if (error == WS_EOF)
|
||||
+ if (error == WS_EOF) {
|
||||
+ /* shutdown is happening, clear peek error */
|
||||
+ ret = 0;
|
||||
break;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (ret == WS_FATAL_ERROR && error == 0) {
|
||||
diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c
|
||||
index a990bc14e..b735c0d51 100644
|
||||
--- a/examples/sftpclient/sftpclient.c
|
||||
+++ b/examples/sftpclient/sftpclient.c
|
||||
@@ -566,11 +566,8 @@ static int doCmds(func_args* args)
|
||||
}
|
||||
|
||||
do {
|
||||
- while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
+ while (wolfSSH_get_error(ssh) == WS_REKEYING) {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
- if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
- ret = wolfSSH_get_error(ssh);
|
||||
- }
|
||||
}
|
||||
|
||||
ret = wolfSSH_SFTP_Get(ssh, pt, to, resume, &myStatusCb);
|
||||
@@ -747,6 +744,13 @@ static int doCmds(func_args* args)
|
||||
|
||||
/* check directory is valid */
|
||||
do {
|
||||
+ while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
+ ret = wolfSSH_worker(ssh, NULL);
|
||||
+ if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
+ ret = wolfSSH_get_error(ssh);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = wolfSSH_SFTP_STAT(ssh, pt, &atrb);
|
||||
err = wolfSSH_get_error(ssh);
|
||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
||||
@@ -828,6 +832,13 @@ static int doCmds(func_args* args)
|
||||
|
||||
/* update permissions */
|
||||
do {
|
||||
+ while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
+ ret = wolfSSH_worker(ssh, NULL);
|
||||
+ if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
+ ret = wolfSSH_get_error(ssh);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = wolfSSH_SFTP_CHMOD(ssh, pt, mode);
|
||||
err = wolfSSH_get_error(ssh);
|
||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
||||
@@ -878,6 +889,13 @@ static int doCmds(func_args* args)
|
||||
}
|
||||
|
||||
do {
|
||||
+ while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
+ ret = wolfSSH_worker(ssh, NULL);
|
||||
+ if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
+ ret = wolfSSH_get_error(ssh);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = wolfSSH_SFTP_RMDIR(ssh, pt);
|
||||
err = wolfSSH_get_error(ssh);
|
||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
||||
@@ -924,6 +942,13 @@ static int doCmds(func_args* args)
|
||||
}
|
||||
|
||||
do {
|
||||
+ while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
+ ret = wolfSSH_worker(ssh, NULL);
|
||||
+ if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
+ ret = wolfSSH_get_error(ssh);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = wolfSSH_SFTP_Remove(ssh, pt);
|
||||
err = wolfSSH_get_error(ssh);
|
||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
||||
@@ -1458,14 +1483,52 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
|
||||
|
||||
WFREE(workingDir, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ret == WS_SUCCESS) {
|
||||
- if (wolfSSH_shutdown(ssh) != WS_SUCCESS) {
|
||||
- int rc;
|
||||
- rc = wolfSSH_get_error(ssh);
|
||||
+ int err;
|
||||
+ ret = wolfSSH_shutdown(ssh);
|
||||
+
|
||||
+ /* peer hung up, stop trying to shutdown */
|
||||
+ if (ret == WS_SOCKET_ERROR_E) {
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+
|
||||
+ err = wolfSSH_get_error(ssh);
|
||||
+ if (err != WS_SOCKET_ERROR_E &&
|
||||
+ (err == WS_WANT_READ || err == WS_WANT_WRITE)) {
|
||||
+ int maxAttempt = 10; /* make 10 attempts max before giving up */
|
||||
+ int attempt;
|
||||
+
|
||||
+ for (attempt = 0; attempt < maxAttempt; attempt++) {
|
||||
+ ret = wolfSSH_worker(ssh, NULL);
|
||||
+ err = wolfSSH_get_error(ssh);
|
||||
+
|
||||
+ /* peer succesfully closed down gracefully */
|
||||
+ if (ret == WS_CHANNEL_CLOSED) {
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
- if (rc != WS_SOCKET_ERROR_E && rc != WS_EOF)
|
||||
- printf("error with wolfSSH_shutdown()\n");
|
||||
+ /* peer hung up, stop shutdown */
|
||||
+ if (ret == WS_SOCKET_ERROR_E) {
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (err == WS_WANT_READ || err == WS_WANT_WRITE) {
|
||||
+ /* Wanting read or wanting write. Clear ret. */
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+ else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (attempt == maxAttempt) {
|
||||
+ printf("SFTP client gave up on gracefull shutdown,"
|
||||
+ "closing the socket\n");
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+
|
||||
WCLOSESOCKET(sockFd);
|
||||
wolfSSH_free(ssh);
|
||||
wolfSSH_CTX_free(ctx);
|
||||
diff --git a/src/wolfsftp.c b/src/wolfsftp.c
|
||||
index a95428fd0..53c5dfd1a 100644
|
||||
--- a/src/wolfsftp.c
|
||||
+++ b/src/wolfsftp.c
|
||||
@@ -865,6 +865,7 @@ static int SFTP_GetHeader(WOLFSSH* ssh, word32* reqId, byte* type,
|
||||
*/
|
||||
static int SFTP_SetHeader(WOLFSSH* ssh, word32 reqId, byte type, word32 len,
|
||||
byte* buf) {
|
||||
+
|
||||
c32toa(len + LENGTH_SZ + MSG_ID_SZ, buf);
|
||||
buf[LENGTH_SZ] = type;
|
||||
c32toa(reqId, buf + LENGTH_SZ + MSG_ID_SZ);
|
||||
@@ -1170,8 +1171,9 @@ int wolfSSH_SFTP_accept(WOLFSSH* ssh)
|
||||
case SFTP_EXT:
|
||||
ret = SFTP_ServerRecvInit(ssh);
|
||||
if (ret != WS_SUCCESS) {
|
||||
- if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE)
|
||||
+ if (!NoticeError(ssh)) {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
|
||||
+ }
|
||||
return ret;
|
||||
}
|
||||
ssh->sftpState = SFTP_RECV;
|
||||
@@ -1573,8 +1575,9 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
|
||||
|
||||
/* break out if encountering an error with nothing stored to send */
|
||||
if (ret < 0 && !state->toSend) {
|
||||
- if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE)
|
||||
+ if (!NoticeError(ssh)) {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV);
|
||||
+ }
|
||||
return ret;
|
||||
}
|
||||
state->buffer.idx = 0;
|
||||
@@ -7674,8 +7677,8 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
/* send header and type specific data */
|
||||
ret = wolfSSH_SFTP_buffer_send(ssh, &state->buffer);
|
||||
if (ret < 0) {
|
||||
- if (ret == WS_REKEYING) {
|
||||
- return ret;
|
||||
+ if (NoticeError(ssh)) {
|
||||
+ return WS_FATAL_ERROR;
|
||||
}
|
||||
if (ssh->error != WS_WANT_READ &&
|
||||
ssh->error != WS_WANT_WRITE) {
|
||||
@@ -7693,14 +7696,12 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
/* Get response */
|
||||
if ((ret = SFTP_GetHeader(ssh, &state->reqId, &state->type,
|
||||
&state->buffer)) <= 0) {
|
||||
- if (ssh->error != WS_WANT_READ &&
|
||||
- ssh->error != WS_WANT_WRITE) {
|
||||
+ if (!NoticeError(ssh)) {
|
||||
state->state = STATE_SEND_READ_CLEANUP;
|
||||
continue;
|
||||
}
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
-
|
||||
ret = wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret);
|
||||
if (ret != WS_SUCCESS) {
|
||||
state->state = STATE_SEND_READ_CLEANUP;
|
||||
@@ -7718,8 +7719,9 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
state->state = STATE_SEND_READ_CLEANUP;
|
||||
continue;
|
||||
}
|
||||
- else
|
||||
+ else {
|
||||
ssh->reqId++;
|
||||
+ }
|
||||
|
||||
if (state->type == WOLFSSH_FTP_DATA)
|
||||
state->state = STATE_SEND_READ_FTP_DATA;
|
||||
@@ -7737,8 +7739,7 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
/* get size of string and place it into out buffer */
|
||||
ret = wolfSSH_stream_read(ssh, szFlat, UINT32_SZ);
|
||||
if (ret < 0) {
|
||||
- if (ssh->error != WS_WANT_READ &&
|
||||
- ssh->error != WS_WANT_WRITE) {
|
||||
+ if (!NoticeError(ssh)) {
|
||||
state->state = STATE_SEND_READ_CLEANUP;
|
||||
continue;
|
||||
}
|
||||
@@ -7917,8 +7918,9 @@ int wolfSSH_SFTP_MKDIR(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||
/* send header and type specific data */
|
||||
ret = wolfSSH_SFTP_buffer_send(ssh, &state->buffer);
|
||||
if (ret < 0) {
|
||||
- if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE)
|
||||
+ if (!NoticeError(ssh)) {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_MKDIR);
|
||||
+ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7931,8 +7933,9 @@ int wolfSSH_SFTP_MKDIR(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||
/* Get response */
|
||||
if ((ret = SFTP_GetHeader(ssh, &state->reqId, &type,
|
||||
&state->buffer)) <= 0) {
|
||||
- if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE)
|
||||
+ if (!NoticeError(ssh)) {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_MKDIR);
|
||||
+ }
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
@@ -7963,8 +7966,9 @@ int wolfSSH_SFTP_MKDIR(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||
if (ret < 0) {
|
||||
- if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE)
|
||||
- wolfSSH_SFTP_ClearState(ssh, STATE_ID_MKDIR);
|
||||
+ if (!NoticeError(ssh)) {
|
||||
+ wolfSSH_SFTP_ClearState(ssh, STATE_ID_MKDIR);
|
||||
+ }
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
@@ -8031,8 +8035,7 @@ WS_SFTPNAME* wolfSSH_SFTP_ReadDir(WOLFSSH* ssh, byte* handle,
|
||||
case STATE_READDIR_NAME:
|
||||
name = wolfSSH_SFTP_DoName(ssh);
|
||||
if (name == NULL) {
|
||||
- if (ssh->error != WS_WANT_READ
|
||||
- && ssh->error != WS_WANT_WRITE) {
|
||||
+ if (!NoticeError(ssh)) {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_READDIR);
|
||||
}
|
||||
return NULL;
|
||||
diff --git a/tests/api.c b/tests/api.c
|
||||
index 2bef34998..701425d20 100644
|
||||
--- a/tests/api.c
|
||||
+++ b/tests/api.c
|
||||
@@ -1075,6 +1075,11 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* take care of re-keying state before shutdown call */
|
||||
+ while (wolfSSH_get_error(ssh) == WS_REKEYING) {
|
||||
+ wolfSSH_worker(ssh, NULL);
|
||||
+ }
|
||||
+
|
||||
argsCount = wolfSSH_shutdown(ssh);
|
||||
if (argsCount == WS_SOCKET_ERROR_E) {
|
||||
/* If the socket is closed on shutdown, peer is gone, this is OK. */
|
||||
|
||||
From 813ec263cc56e7c9093135d854b3fc887633d368 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Tue, 16 Sep 2025 13:52:12 -0600
|
||||
Subject: [PATCH 6/8] fix for scan-build report of unused return value
|
||||
|
||||
---
|
||||
examples/sftpclient/sftpclient.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c
|
||||
index b735c0d51..1194b0de5 100644
|
||||
--- a/examples/sftpclient/sftpclient.c
|
||||
+++ b/examples/sftpclient/sftpclient.c
|
||||
@@ -566,8 +566,11 @@ static int doCmds(func_args* args)
|
||||
}
|
||||
|
||||
do {
|
||||
- while (wolfSSH_get_error(ssh) == WS_REKEYING) {
|
||||
+ while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
+ if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
+ ret = wolfSSH_get_error(ssh);
|
||||
+ }
|
||||
}
|
||||
|
||||
ret = wolfSSH_SFTP_Get(ssh, pt, to, resume, &myStatusCb);
|
||||
|
||||
From cc17941a6125daefbadb8c236fdeaeb1a21ec786 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Tue, 16 Sep 2025 14:16:16 -0600
|
||||
Subject: [PATCH 7/8] adjust test case to account for re-keying return
|
||||
|
||||
---
|
||||
tests/api.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tests/api.c b/tests/api.c
|
||||
index 701425d20..9da02849b 100644
|
||||
--- a/tests/api.c
|
||||
+++ b/tests/api.c
|
||||
@@ -1057,14 +1057,16 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
|
||||
outSz = WOLFSSH_MAX_SFTP_RW / 2;
|
||||
rxSz = wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz,
|
||||
ofst, out, outSz);
|
||||
- AssertIntGT(rxSz, 0);
|
||||
- AssertIntLE(rxSz, outSz);
|
||||
+ if (wolfSSH_get_error(ssh) != WS_REKEYING) {
|
||||
+ AssertIntGT(rxSz, 0);
|
||||
+ AssertIntLE(rxSz, outSz);
|
||||
+ }
|
||||
|
||||
/* read all */
|
||||
outSz = WOLFSSH_MAX_SFTP_RW;
|
||||
rxSz = wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz,
|
||||
ofst, out, outSz);
|
||||
- if (rxSz != WS_REKEYING) {
|
||||
+ if (wolfSSH_get_error(ssh) != WS_REKEYING) {
|
||||
AssertIntGT(rxSz, 0);
|
||||
AssertIntLE(rxSz, outSz);
|
||||
}
|
||||
|
||||
From 4862400a374253216e596ff5c3b018b857015cbb Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Mon, 6 Oct 2025 00:42:05 -0600
|
||||
Subject: [PATCH 8/8] fix spelling issues and SFTP send state
|
||||
|
||||
---
|
||||
.github/workflows/sshd-test.yml | 2 +-
|
||||
examples/client/client.c | 4 ++--
|
||||
examples/sftpclient/sftpclient.c | 7 ++++---
|
||||
src/internal.c | 2 +-
|
||||
src/wolfsftp.c | 15 +++++++++------
|
||||
5 files changed, 17 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/.github/workflows/sshd-test.yml b/.github/workflows/sshd-test.yml
|
||||
index eb075a6f1..3fbe3daf8 100644
|
||||
--- a/.github/workflows/sshd-test.yml
|
||||
+++ b/.github/workflows/sshd-test.yml
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
wolfssl: ${{ fromJson(needs.create_matrix.outputs['versions']) }}
|
||||
name: Build and test wolfsshd
|
||||
runs-on: ${{ matrix.os }}
|
||||
- timeout-minutes: 15
|
||||
+ timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checking cache for wolfssl
|
||||
uses: actions/cache@v4
|
||||
diff --git a/examples/client/client.c b/examples/client/client.c
|
||||
index f415bd801..49d00f44f 100644
|
||||
--- a/examples/client/client.c
|
||||
+++ b/examples/client/client.c
|
||||
@@ -481,10 +481,10 @@ static THREAD_RET readPeer(void* in)
|
||||
}
|
||||
}
|
||||
else if (ret != WS_EOF) {
|
||||
- if (ret == 0) {
|
||||
+ if (ret == 0) {
|
||||
bytes = 0;
|
||||
continue;
|
||||
- }
|
||||
+ }
|
||||
err_sys("Stream read failed.");
|
||||
}
|
||||
}
|
||||
diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c
|
||||
index 1194b0de5..e074b3d13 100644
|
||||
--- a/examples/sftpclient/sftpclient.c
|
||||
+++ b/examples/sftpclient/sftpclient.c
|
||||
@@ -1184,7 +1184,7 @@ static int doAutopilot(int cmd, char* local, char* remote)
|
||||
}
|
||||
|
||||
do {
|
||||
- if (err == WS_REKEYING) { /* handle rekeying state */
|
||||
+ if (err == WS_REKEYING || err == WS_WINDOW_FULL) { /* handle rekeying state */
|
||||
do {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
} while (ret == WS_REKEYING);
|
||||
@@ -1198,7 +1198,8 @@ static int doAutopilot(int cmd, char* local, char* remote)
|
||||
}
|
||||
err = wolfSSH_get_error(ssh);
|
||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE ||
|
||||
- err == WS_CHAN_RXD || err == WS_REKEYING) &&
|
||||
+ err == WS_CHAN_RXD || err == WS_REKEYING ||
|
||||
+ err == WS_WINDOW_FULL) &&
|
||||
ret == WS_FATAL_ERROR);
|
||||
|
||||
if (ret != WS_SUCCESS) {
|
||||
@@ -1504,7 +1505,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
err = wolfSSH_get_error(ssh);
|
||||
|
||||
- /* peer succesfully closed down gracefully */
|
||||
+ /* peer successfully closed down gracefully */
|
||||
if (ret == WS_CHANNEL_CLOSED) {
|
||||
ret = 0;
|
||||
break;
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index ff912ef74..b9e3a3432 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -605,7 +605,7 @@ INLINE static int IsMessageAllowedKeying(WOLFSSH *ssh, byte msg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
- /* case of servie request or accept in 1-19 */
|
||||
+ /* case of service request or accept in 1-19 */
|
||||
if (msg == MSGID_SERVICE_REQUEST || msg == MSGID_SERVICE_ACCEPT) {
|
||||
WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by during rekeying", msg);
|
||||
ssh->error = WS_REKEYING;
|
||||
diff --git a/src/wolfsftp.c b/src/wolfsftp.c
|
||||
index 53c5dfd1a..998806aef 100644
|
||||
--- a/src/wolfsftp.c
|
||||
+++ b/src/wolfsftp.c
|
||||
@@ -416,6 +416,7 @@ static INLINE int NoticeError(WOLFSSH* ssh)
|
||||
return (ssh->error == WS_WANT_READ ||
|
||||
ssh->error == WS_WANT_WRITE ||
|
||||
ssh->error == WS_CHAN_RXD ||
|
||||
+ ssh->error == WS_WINDOW_FULL ||
|
||||
ssh->error == WS_REKEYING);
|
||||
}
|
||||
|
||||
@@ -865,7 +866,6 @@ static int SFTP_GetHeader(WOLFSSH* ssh, word32* reqId, byte* type,
|
||||
*/
|
||||
static int SFTP_SetHeader(WOLFSSH* ssh, word32 reqId, byte type, word32 len,
|
||||
byte* buf) {
|
||||
-
|
||||
c32toa(len + LENGTH_SZ + MSG_ID_SZ, buf);
|
||||
buf[LENGTH_SZ] = type;
|
||||
c32toa(reqId, buf + LENGTH_SZ + MSG_ID_SZ);
|
||||
@@ -7471,12 +7471,15 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||
case STATE_SEND_WRITE_SEND_BODY:
|
||||
WLOG(WS_LOG_SFTP, "SFTP SEND_WRITE STATE: SEND_BODY");
|
||||
state->sentSz = wolfSSH_stream_send(ssh, in, inSz);
|
||||
- if (NoticeError(ssh)) {
|
||||
- return WS_FATAL_ERROR;
|
||||
- }
|
||||
if (state->sentSz <= 0) {
|
||||
- ssh->error = state->sentSz;
|
||||
ret = WS_FATAL_ERROR;
|
||||
+ if (NoticeError(ssh)) {
|
||||
+ ret = wolfSSH_worker(ssh,NULL);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* if it was not a notice error then clean up the state and
|
||||
+ * exit out */
|
||||
state->state = STATE_SEND_WRITE_CLEANUP;
|
||||
continue;
|
||||
}
|
||||
@@ -9170,7 +9173,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
||||
if (sz <= 0) {
|
||||
if (NoticeError(ssh)) {
|
||||
return WS_FATAL_ERROR;
|
||||
- }
|
||||
+ }
|
||||
}
|
||||
else {
|
||||
AddAssign64(state->pOfst, sz);
|
||||
@@ -0,0 +1,46 @@
|
||||
From 201029797b260eee894b12d488bce6022290bf67 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Fri, 18 Jul 2025 15:43:26 -0600
|
||||
Subject: [PATCH] only send ext info once after SSH_MSG_NEWKEYS
|
||||
|
||||
---
|
||||
src/internal.c | 6 +++++-
|
||||
wolfssh/internal.h | 1 +
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index 080ded6f3..912315ca2 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -4080,7 +4080,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
if (ret == WS_SUCCESS) {
|
||||
/* Only checking for this is we are server. Our client does
|
||||
* not have anything to say to a server, yet. */
|
||||
- if (side == WOLFSSH_ENDPOINT_SERVER) {
|
||||
+ if (side == WOLFSSH_ENDPOINT_SERVER && !ssh->extInfoSent) {
|
||||
byte extInfo;
|
||||
|
||||
/* Match the client accepts extInfo. */
|
||||
@@ -13216,6 +13216,10 @@ int SendExtInfo(WOLFSSH* ssh)
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
+ ssh->sendExtInfo = 0;
|
||||
+ ssh->extInfoSent = 1; /* RFC 8308 section 2.4 ext. info should only be
|
||||
+ * sent after SSH_MSG_NEWKEYS or after
|
||||
+ * SSH_MSG_USERAUTH_SUCCESS. Not on re-key */
|
||||
ret = wolfSSH_SendPacket(ssh);
|
||||
}
|
||||
|
||||
diff --git a/wolfssh/internal.h b/wolfssh/internal.h
|
||||
index 1b60139a1..26c3a05b0 100644
|
||||
--- a/wolfssh/internal.h
|
||||
+++ b/wolfssh/internal.h
|
||||
@@ -844,6 +844,7 @@ struct WOLFSSH {
|
||||
byte sendTerminalRequest;
|
||||
byte userAuthPkDone;
|
||||
byte sendExtInfo;
|
||||
+ byte extInfoSent; /* track if the ext info has already been sent */
|
||||
byte* peerSigId;
|
||||
word32 peerSigIdSz;
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
From 9dc1071da7e560db2ea899fa23aab885a25ea862 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Mon, 13 Oct 2025 09:44:29 -0600
|
||||
Subject: [PATCH 1/2] improvements to keying and track side
|
||||
|
||||
---
|
||||
src/internal.c | 35 ++++++++++++++++++++++++++++++-----
|
||||
wolfssh/internal.h | 5 +++++
|
||||
2 files changed, 35 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index edab14eb4..230904489 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -1096,7 +1096,7 @@ WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
|
||||
ssh->fs = NULL;
|
||||
ssh->acceptState = ACCEPT_BEGIN;
|
||||
ssh->clientState = CLIENT_BEGIN;
|
||||
- ssh->isKeying = 1;
|
||||
+ ssh->isKeying = 0; /* initial state of not keying yet */
|
||||
ssh->authId = ID_USERAUTH_PUBLICKEY;
|
||||
ssh->supportedAuth[0] = ID_USERAUTH_PUBLICKEY;
|
||||
ssh->supportedAuth[1] = ID_USERAUTH_PASSWORD;
|
||||
@@ -4058,6 +4058,15 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
+ if (ret == WS_SUCCESS) {
|
||||
+ /* Check if already in process of keying and error out if so. */
|
||||
+ if (ssh->isKeying & WOLFSSH_PEER_IS_KEYING) {
|
||||
+ WLOG(WS_LOG_ERROR,
|
||||
+ "Already in keying process and got KEX init");
|
||||
+ ret = WS_INVALID_STATE_E;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* I don't need to save what the client sends here. I should decode
|
||||
* each list into a local array of IDs, and pick the one the peer is
|
||||
@@ -4067,6 +4076,8 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
*/
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
+ /* Set peer is keying flag after receiving SSH_MSG_KEX_INIT */
|
||||
+ ssh->isKeying |= WOLFSSH_PEER_IS_KEYING;
|
||||
if (ssh->handshake == NULL) {
|
||||
ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);
|
||||
if (ssh->handshake == NULL) {
|
||||
@@ -5881,6 +5892,13 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
if (ssh == NULL || ssh->handshake == NULL)
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
|
||||
+ if (ret == WS_SUCCESS) {
|
||||
+ if (ssh->isKeying & WOLFSSH_SELF_IS_KEYING) {
|
||||
+ WLOG(WS_LOG_ERROR, "Keying failed");
|
||||
+ ret = WS_INVALID_STATE_E;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (ret == WS_SUCCESS) {
|
||||
ssh->peerEncryptId = ssh->handshake->encryptId;
|
||||
ssh->peerMacId = ssh->handshake->macId;
|
||||
@@ -5941,7 +5959,9 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
if (ret == WS_SUCCESS) {
|
||||
ssh->rxCount = 0;
|
||||
ssh->highwaterFlag = 0;
|
||||
- ssh->isKeying = 0;
|
||||
+
|
||||
+ /* Clear peer is keying flag */
|
||||
+ ssh->isKeying &= ~WOLFSSH_PEER_IS_KEYING;
|
||||
HandshakeInfoFree(ssh->handshake, ssh->ctx->heap);
|
||||
ssh->handshake = NULL;
|
||||
WLOG(WS_LOG_DEBUG, "Keying completed");
|
||||
@@ -9405,7 +9425,7 @@ static int DoPacket(WOLFSSH* ssh, byte* bufferConsumed)
|
||||
case MSGID_KEXINIT:
|
||||
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXINIT");
|
||||
ret = DoKexInit(ssh, buf + idx, payloadSz, &payloadIdx);
|
||||
- if (ssh->isKeying == 1 &&
|
||||
+ if (ssh->isKeying &&
|
||||
ssh->connectState == CONNECT_SERVER_CHANNEL_REQUEST_DONE) {
|
||||
if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {
|
||||
#if !defined(WOLFSSH_NO_DH) && !defined(WOLFSSH_NO_DH_GEX_SHA256)
|
||||
@@ -10501,7 +10521,8 @@ int SendKexInit(WOLFSSH* ssh)
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
- ssh->isKeying = 1;
|
||||
+ /* Set self is keying flag since we started sending the KEX init msg */
|
||||
+ ssh->isKeying |= WOLFSSH_SELF_IS_KEYING;
|
||||
if (ssh->handshake == NULL) {
|
||||
ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);
|
||||
if (ssh->handshake == NULL) {
|
||||
@@ -12534,9 +12555,13 @@ int SendNewKeys(WOLFSSH* ssh)
|
||||
ssh->txCount = 0;
|
||||
}
|
||||
|
||||
- if (ret == WS_SUCCESS)
|
||||
+ if (ret == WS_SUCCESS) {
|
||||
ret = wolfSSH_SendPacket(ssh);
|
||||
|
||||
+ /* Clear self is keying flag */
|
||||
+ ssh->isKeying &= ~WOLFSSH_SELF_IS_KEYING;
|
||||
+ }
|
||||
+
|
||||
WLOG(WS_LOG_DEBUG, "Leaving SendNewKeys(), ret = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
diff --git a/wolfssh/internal.h b/wolfssh/internal.h
|
||||
index 1b7dada16..6df5f1147 100644
|
||||
--- a/wolfssh/internal.h
|
||||
+++ b/wolfssh/internal.h
|
||||
@@ -473,6 +473,11 @@ enum NameIdType {
|
||||
#define WOLFSSH_KEY_QUANTITY_REQ 1
|
||||
#endif
|
||||
|
||||
+/* Keep track of keying state for both sides of the connection.
|
||||
+ * WOLFSSH_SELF_IS_KEYING gets set on sending KEX init and
|
||||
+ * WOLFSSH_PEER_IS_KEYING gets set on receiving KEX init */
|
||||
+#define WOLFSSH_PEER_IS_KEYING 0x01
|
||||
+#define WOLFSSH_SELF_IS_KEYING 0x02
|
||||
|
||||
WOLFSSH_LOCAL byte NameToId(const char* name, word32 nameSz);
|
||||
WOLFSSH_LOCAL const char* IdToName(byte id);
|
||||
|
||||
From 024b14124aa2434e90468408b94121c897311f37 Mon Sep 17 00:00:00 2001
|
||||
From: JacobBarthelmeh <jacob@wolfssl.com>
|
||||
Date: Mon, 13 Oct 2025 22:47:45 -0600
|
||||
Subject: [PATCH 2/2] update Kex Init response after adding keying track sides
|
||||
|
||||
---
|
||||
src/internal.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index 230904489..db70d0f6f 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -4338,7 +4338,8 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
byte scratchLen[LENGTH_SZ];
|
||||
word32 strSz = 0;
|
||||
|
||||
- if (!ssh->isKeying) {
|
||||
+ /* respond with KEX Init message if not having initiated the keying */
|
||||
+ if ((ssh->isKeying & WOLFSSH_SELF_IS_KEYING) == 0) {
|
||||
WLOG(WS_LOG_DEBUG, "Keying initiated");
|
||||
ret = SendKexInit(ssh);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
From e9d288ec603531a1d544e77fb1bbdf634cb2a57f Mon Sep 17 00:00:00 2001
|
||||
From: John Safranek <john@wolfssl.com>
|
||||
Date: Mon, 13 Apr 2026 15:05:48 -0700
|
||||
Subject: [PATCH] Server Does Not Set expectMsgId to MSGID_NEWKEYS
|
||||
|
||||
In the server code, the server is not setting the expectedMsgId to
|
||||
MSGID_NEWKEYS before sending its new keys message. Update DoKexDhReply()
|
||||
to set expectMsgId to MSGID_NEWKEYS.
|
||||
|
||||
Affected function: DoKeyDhReply.
|
||||
Issue: F-1275
|
||||
---
|
||||
src/internal.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/internal.c b/src/internal.c
|
||||
index 970bece9b..511d77ef2 100644
|
||||
--- a/src/internal.c
|
||||
+++ b/src/internal.c
|
||||
@@ -12914,8 +12914,11 @@ int SendKexDhReply(WOLFSSH* ssh)
|
||||
ret = BundlePacket(ssh);
|
||||
}
|
||||
|
||||
- if (ret == WS_SUCCESS)
|
||||
+ if (ret == WS_SUCCESS) {
|
||||
+ ssh->handshake->expectMsgId = MSGID_NEWKEYS;
|
||||
+ WLOG_EXPECT_MSGID(ssh->handshake->expectMsgId);
|
||||
ret = SendNewKeys(ssh);
|
||||
+ }
|
||||
|
||||
if (ret == WS_SUCCESS && ssh->sendExtInfo) {
|
||||
ret = SendExtInfo(ssh);
|
||||
@@ -0,0 +1,155 @@
|
||||
# wolfSSH 1.4.20 restricted ordering correction
|
||||
|
||||
Project modification: **2026-09-16**. This is a bounded project-profile correction
|
||||
for the CVE-2025-14942 ordering defect, **not a complete wolfSSH 1.4.22/1.5.0
|
||||
backport or general-purpose upstream-fix claim**. wolfSSH remains pinned to
|
||||
1.4.20; wolfSSL and all existing password/parser/crypto protections remain pinned
|
||||
and intact. No managed source is edited.
|
||||
|
||||
## Inputs and provenance
|
||||
|
||||
`793.patch`, `819.patch`, `840.patch`, `855.patch`, and `921.patch` are the exact
|
||||
upstream mail-patch responses fetched on 2026-09-16. `provenance.json` records
|
||||
URLs, byte SHA-256 hashes, and every embedded full commit ID. PR endpoints can
|
||||
change: the archived bytes and commit identities, not a future PR response,
|
||||
identify this review. Commit pages are recoverable as
|
||||
`https://github.com/wolfSSL/wolfssh/commit/<commit>`.
|
||||
|
||||
`delta.json` is the **authoritative executable consolidated delta**, not a claim
|
||||
that all archived hunks apply. Its exact old/new edits are applied before the
|
||||
existing parser/password edits by `tools/security_overrides.py`; every anchor
|
||||
must occur exactly once. It pins:
|
||||
|
||||
| Input | Original SHA-256 |
|
||||
| --- | --- |
|
||||
| `src/internal.c` | `81ff1f9166708abd5c2911e9fe57c0aee01c88b5d3f68c909ee8a856d37f36a9` |
|
||||
| `src/ssh.c` | `a4f479ff87eea0980ec1ebdf2c7dd090da473780181b695a56799cb9611f4366` |
|
||||
| `wolfssh/internal.h` | `8e417149a68f8a6c0506957adf014b3e6c1727a723536826ce5fb0c9e1f1aba3` |
|
||||
|
||||
Original copyright/license notices remain in each generated file, preceded by
|
||||
project modification/provenance notices. Configuration needs no network,
|
||||
`patch(1)`, Git, or fuzzy matching. All inputs validate before outputs are written.
|
||||
|
||||
### Prerequisite disposition
|
||||
|
||||
- **PR793:** retain stream/channel read rekey fencing, stream-send fatal/error
|
||||
convention, EOF/window-adjust send checks and send/receive direction constants.
|
||||
Exclude example, SFTP, workflow and upstream-test changes. The intermediate
|
||||
`IsMessageAllowedKeying` implementation was removed by PR855 itself; it is not
|
||||
resurrected. Local send checks are distinct from receive checks. The follow-up
|
||||
corrects a misapplied EOF hunk: `SendChannelEof` now checks before lookup,
|
||||
serialization or `eofTxd` mutation. The extra `SendChannelExit` guard is retained
|
||||
intentionally as local hardening, using `MSGID_CHANNEL_REQUEST` (exit-status),
|
||||
not falsely attributed to PR793's EOF hunk. Real shutdown/rekey tests cover both.
|
||||
- **PR819:** retain `extInfoSent` ABI field, but supersede its negotiation/send
|
||||
logic by disabling EXT_INFO uniformly. The field stays zero; no reset-on-rekey
|
||||
or exactly-once extension continuation is needed.
|
||||
- **PR840:** initialize keying to zero; maintain independent SELF/PEER bits;
|
||||
reject duplicate peer KEXINIT; respond only if SELF was not already keying;
|
||||
reject peer NEWKEYS while SELF still owes NEWKEYS; clear PEER and release the
|
||||
handshake only after successful incoming key installation.
|
||||
- **PR855:** retain `expectMsgId`, message IDs/ranges, and expected-reply writes
|
||||
**before** nonblocking sends. Adapt the client `DoKexDhReply` hunk to 1.4.20's
|
||||
`useEccKyber` spelling; no PQ algorithm is enabled. Replace permissive range
|
||||
fallthrough with the explicit restricted gates described below. Upstream
|
||||
test-only entry points/build rules are not imported. Its new log macro is
|
||||
local to generated `internal.c`: the pinned `log.h` has a different WLOG
|
||||
implementation, so neither `log.h` nor `log.c` needs an ABI/source change.
|
||||
- **PR921:** set server `expectMsgId = MSGID_NEWKEYS` before `SendNewKeys`, including
|
||||
WANT_WRITE. The former post-NEWKEYS EXT_INFO call is deliberately removed.
|
||||
|
||||
Local additions also set the server's expected INIT after valid KEXINIT, retain
|
||||
that expectation after skipping a wrong optimistic INIT guess, reject absent
|
||||
expectations instead of accepting arbitrary KEX packets, and only allow client
|
||||
rekey dispatch after successful/queued KEXINIT with a live handshake. Client
|
||||
rekey dispatch includes the final `CONNECT_DONE` state.
|
||||
|
||||
## Restricted protocol contract
|
||||
|
||||
- Negotiate only the existing project KEX profile: **Curve25519-SHA256 and
|
||||
ECDH-P256**. A caller trying to widen the algorithm list to DH/GEX/PQ gets a
|
||||
negotiation error. Those continuation paths are not represented as supported.
|
||||
- Receive transport notifications 1–4 without consuming an expected KEX reply.
|
||||
KEXINIT is legal only before the peer has begun this exchange; other KEX
|
||||
messages require a live handshake and an exact nonzero expectation. Acceptance
|
||||
consumes that expectation once; the handler sets the next expectation.
|
||||
- Reject authentication/service/connection traffic after **peer** KEXINIT until
|
||||
peer NEWKEYS. When only SELF has initiated rekey, pre-peer-KEXINIT in-flight
|
||||
traffic remains legal according to the authentication phase (RFC4253).
|
||||
- Server requires keyed service request, then service acceptance before userauth
|
||||
requests, then completed authentication before connection messages. Reject
|
||||
wrong-direction and repeated authentication/service messages. Client rejects
|
||||
premature auth results/channel messages and accepts auth responses only in
|
||||
its request phase. Keyboard-interactive is outside the project profile and
|
||||
incoming INFO_RESPONSE is rejected before dispatch.
|
||||
- Send-side EOF/window-adjust checks never mutate receive expectations. Existing
|
||||
channel-data rekey fencing is preserved.
|
||||
|
||||
### NEWKEYS/backpressure and the EXT_INFO choice
|
||||
|
||||
`SendNewKeys` bundles NEWKEYS with the old sending keys, installs the new sending
|
||||
keys, then calls `wolfSSH_SendPacket`. `WS_WANT_WRITE` means that **same bundled
|
||||
packet** remains in the bounded output buffer. Clear SELF on SUCCESS or
|
||||
WANT_WRITE, retain PEER and the expected peer NEWKEYS. The existing
|
||||
accept/connect/worker flush paths send the remaining bytes; they must not call
|
||||
`SendNewKeys` again. A fatal send does not clear SELF. Peer NEWKEYS installs the
|
||||
receive keys and releases the handshake once; premature/duplicate NEWKEYS fails.
|
||||
|
||||
Previously `SendKexDhReply` called `SendExtInfo` only on SUCCESS from NEWKEYS. A
|
||||
partial send skipped it with no continuation. Rather than invent another pending
|
||||
send state and its handshake-lifetime rules, this profile:
|
||||
|
||||
1. Does not append `ext-info-c` to client KEXINIT.
|
||||
2. Ignores peers' extension willingness; sets `sendExtInfo` to zero on KEXINIT.
|
||||
3. Removes the post-NEWKEYS extension send and makes `SendExtInfo` return
|
||||
`WS_NOT_COMPILED` even if called directly.
|
||||
4. Rejects incoming EXT_INFO in every phase, since it was never negotiated.
|
||||
|
||||
This follows RFC8308's optional-negotiation model. **There is no
|
||||
`server-sig-algs` advertisement.** The existing KeyAccepted setter remains valid
|
||||
but no longer produces that extension on the wire. This matters particularly to
|
||||
RSA-SHA2 discovery: RSA user keys are outside the project's enrolled/advertised
|
||||
profile, and RSA interoperability is not claimed. Host tests establish that
|
||||
OpenSSH 10.2p1 still authenticates using Ed25519, P-256 and passwords with both
|
||||
project KEX algorithms, initial KEX and rekeys, without receiving EXT_INFO.
|
||||
Other clients and hardware remain validation work.
|
||||
|
||||
## Header overlay and build ownership
|
||||
|
||||
The ABI changes require **all** consumers to use the generated header, not only
|
||||
the relocated C file. `cmake/security_overrides.cmake` installs
|
||||
`security_overrides/wolfssh_include/wolfssh/internal.h` with BEFORE PUBLIC include
|
||||
propagation and a PUBLIC forced include. The original header's include guard
|
||||
prevents a later vendor-first include path from defining a stale layout. A dated
|
||||
ABI marker rejects an original header forcibly included *before* the overlay,
|
||||
rather than silently skipping the corrected layout. Existing
|
||||
unmodified wolfSSH files and transitive application consumers therefore use the
|
||||
same layout. Source properties are retained; header originals, generated header,
|
||||
and `delta.json` are configure dependencies. Compiler dependencies track the
|
||||
forced header too. There are now **eight source overrides plus one header**.
|
||||
|
||||
Tests intentionally put the original include root before the overlay when
|
||||
compiling full host translation units. The SDK CMake fixture checks PUBLIC
|
||||
propagation to library, direct and transitive consumers. Forced headers use joined
|
||||
`-include/path` arguments: PlatformIO sorts app flags and deduplicates component
|
||||
flags, which breaks split option/operand pairs. The installed adapter/SCons test
|
||||
compiles a real Xtensa consumer and reproduces the failure with a split-option
|
||||
mutation. The crypto guard remains enabled with its existing joined argument.
|
||||
The obsolete unused EXT_INFO name constant is removed, without relaxing warnings.
|
||||
|
||||
## Validation and boundaries
|
||||
|
||||
Run `python3 tests/wolfssh_order_contract/run.py --interop` and the related
|
||||
commands listed in that test's README. Tests execute the actual generated full
|
||||
`internal.c` and `ssh.c` with real wolfCrypt, bounded host IO, hostile message-ID
|
||||
matrices, partial writes, both roles and all three rekey initiation directions.
|
||||
Guard-removal mutations must fail. The parser/password suites separately preserve
|
||||
prior protections; SDK tests exercise real override/overlay CMake wiring.
|
||||
|
||||
Follow-up validation on 2026-09-16: authorized `pio run` PASS in 21.31 seconds,
|
||||
**94,340 B linked RAM / 1,768,701 B flash**. Strict auth, protocol, crypto and
|
||||
SDK override tests against the rebuilt production artifacts PASS. Ordering tests
|
||||
PASS 8,028 checks and seven rejected mutations; parser tests PASS 3,124 cases in
|
||||
each stack mode. No upload, erase, dependency upgrade or device operation.
|
||||
This does not establish stack/heap reserve, timing, arbitrary-algorithm,
|
||||
strict-KEX-extension, full-client compatibility or phase-wide security sign-off.
|
||||
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"src/internal.c": {
|
||||
"sha256": "81ff1f9166708abd5c2911e9fe57c0aee01c88b5d3f68c909ee8a856d37f36a9",
|
||||
"edits": [
|
||||
{
|
||||
"old": " * API calls into this module to do the work of processing the connections.\n */\n\n\n#ifdef HAVE_CONFIG_H\n #include <config.h>\n#endif\n\n#include <stdio.h>\n#include <wolfssh/ssh.h>\n#include <wolfssh/internal.h>\n#include <wolfssh/log.h>\n#include <wolfssl/version.h>\n#include <wolfssl/wolfcrypt/asn.h>\n#ifndef WOLFSSH_NO_DH\n #include <wolfssl/wolfcrypt/dh.h>\n#endif\n#include <wolfssl/wolfcrypt/curve25519.h>\n#include <wolfssl/wolfcrypt/ed25519.h>\n#ifdef WOLFSSH_CERTS\n #include <wolfssl/wolfcrypt/error-crypt.h>\n#endif\n#include <wolfssl/wolfcrypt/rsa.h>\n#include <wolfssl/wolfcrypt/ecc.h>\n",
|
||||
"new": " * API calls into this module to do the work of processing the connections.\n */\n\n\n#ifdef HAVE_CONFIG_H\n #include <config.h>\n#endif\n\n#include <stdio.h>\n#include <wolfssh/ssh.h>\n#include <wolfssh/internal.h>\n#include <wolfssh/log.h>\n#define WLOG_EXPECT_MSGID(x) WLOG(WS_LOG_DEBUG, \"Expecting message %d\", (x))\n#include <wolfssl/version.h>\n#include <wolfssl/wolfcrypt/asn.h>\n#ifndef WOLFSSH_NO_DH\n #include <wolfssl/wolfcrypt/dh.h>\n#endif\n#include <wolfssl/wolfcrypt/curve25519.h>\n#include <wolfssl/wolfcrypt/ed25519.h>\n#ifdef WOLFSSH_CERTS\n #include <wolfssl/wolfcrypt/error-crypt.h>\n#endif\n#include <wolfssl/wolfcrypt/rsa.h>\n#include <wolfssl/wolfcrypt/ecc.h>\n"
|
||||
},
|
||||
{
|
||||
"old": " WFREE(hs->primeGroup, heap, DYNTYPE_MPINT);\n WFREE(hs->generator, heap, DYNTYPE_MPINT);\n#endif\n if (hs->kexHashId != WC_HASH_TYPE_NONE) {\n wc_HashFree(&hs->kexHash, (enum wc_HashType)hs->kexHashId);\n }\n ForceZero(hs, sizeof(HandshakeInfo));\n WFREE(hs, heap, DYNTYPE_HS);\n }\n}\n\n\n#ifndef NO_WOLFSSH_SERVER\nINLINE static int IsMessageAllowedServer(WOLFSSH *ssh, byte msg)\n{\n /* Has client userauth started? */\n if (ssh->acceptState < ACCEPT_KEYED) {\n if (msg > MSGID_KEXDH_LIMIT) {\n return 0;\n }\n }\n /* Is server userauth complete? */\n if (ssh->acceptState < ACCEPT_SERVER_USERAUTH_SENT) {\n /* Explicitly check for messages not allowed before user\n * authentication has comleted. */\n if (msg >= MSGID_USERAUTH_LIMIT) {\n WLOG(WS_LOG_DEBUG, \"Message ID %u not allowed by server \"\n \"before user authentication is complete\", msg);\n return 0;\n }\n /* Explicitly check for the user authentication messages that\n * only the server sends, it shouldn't receive them. */\n if ((msg > MSGID_USERAUTH_RESTRICT) &&\n (msg != MSGID_USERAUTH_INFO_RESPONSE)) {\n WLOG(WS_LOG_DEBUG, \"Message ID %u not allowed by server \"\n \"during user authentication\", msg);\n return 0;\n }\n }\n else {\n if (msg >= MSGID_USERAUTH_RESTRICT && msg < MSGID_USERAUTH_LIMIT) {\n WLOG(WS_LOG_DEBUG, \"Message ID %u not allowed by server \"\n \"after user authentication\", msg);\n return 0;\n }\n }\n\n return 1;\n}\n#endif /* NO_WOLFSSH_SERVER */\n\n\n#ifndef NO_WOLFSSH_CLIENT\nINLINE static int IsMessageAllowedClient(WOLFSSH *ssh, byte msg)\n{\n /* Has client userauth started? */\n if (ssh->connectState < CONNECT_CLIENT_KEXDH_INIT_SENT) {\n if (msg >= MSGID_KEXDH_LIMIT) {\n return 0;\n }\n }\n /* Is client userauth complete? */\n if (ssh->connectState < CONNECT_SERVER_USERAUTH_ACCEPT_DONE) {\n /* Explicitly check for messages not allowed before user\n * authentication has comleted. */\n if (msg >= MSGID_USERAUTH_LIMIT) {\n WLOG(WS_LOG_DEBUG, \"Message ID %u not allowed by client \"\n \"before user authentication is complete\", msg);\n return 0;\n }\n /* Explicitly check for the user authentication message that\n * only the client sends, it shouldn't receive it. */\n if (msg == MSGID_USERAUTH_RESTRICT) {\n WLOG(WS_LOG_DEBUG, \"Message ID %u not allowed by client \"\n \"during user authentication\", msg);\n return 0;\n }\n }\n else {\n if (msg >= MSGID_USERAUTH_RESTRICT && msg < MSGID_USERAUTH_LIMIT) {\n WLOG(WS_LOG_DEBUG, \"Message ID %u not allowed by client \"\n \"after user authentication\", msg);\n return 0;\n }\n }\n return 1;\n}\n#endif /* NO_WOLFSSH_CLIENT */\n\n\nINLINE static int IsMessageAllowed(WOLFSSH *ssh, byte msg)\n{\n#ifndef NO_WOLFSSH_SERVER\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {\n return IsMessageAllowedServer(ssh, msg);\n }\n#endif /* NO_WOLFSSH_SERVER */\n#ifndef NO_WOLFSSH_CLIENT\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_CLIENT) {\n return IsMessageAllowedClient(ssh, msg);\n }\n#endif /* NO_WOLFSSH_CLIENT */\n return 0;\n}\n\n\nstatic const char cannedKexAlgoNames[] =\n#if !defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256)\n \"ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org,\"\n#endif\n#ifndef WOLFSSH_NO_CURVE25519_SHA256\n \"curve25519-sha256,\"\n#endif\n#if !defined(WOLFSSH_NO_ECDH_SHA2_NISTP521)\n",
|
||||
"new": " WFREE(hs->primeGroup, heap, DYNTYPE_MPINT);\n WFREE(hs->generator, heap, DYNTYPE_MPINT);\n#endif\n if (hs->kexHashId != WC_HASH_TYPE_NONE) {\n wc_HashFree(&hs->kexHash, (enum wc_HashType)hs->kexHashId);\n }\n ForceZero(hs, sizeof(HandshakeInfo));\n WFREE(hs, heap, DYNTYPE_HS);\n }\n}\n\n\n/* Project restricted ordering profile, derived from wolfSSH PR855.\n * EXT_INFO is deliberately not negotiated. See README.md for scope.\n * This fragment is installed into the pinned internal.c by the exact delta.\n */\n#ifndef NO_WOLFSSH_SERVER\nINLINE static int IsMessageAllowedServer(WOLFSSH* ssh, byte msg)\n{\n if (msg == MSGID_SERVICE_REQUEST)\n return ssh->acceptState == ACCEPT_KEYED;\n if (msg == MSGID_USERAUTH_REQUEST)\n return ssh->acceptState >= ACCEPT_SERVER_USERAUTH_ACCEPT_SENT &&\n ssh->acceptState < ACCEPT_SERVER_USERAUTH_SENT;\n /* Keyboard-interactive is not part of the project profile. */\n return MSGIDLIMIT_POST_USERAUTH(msg) &&\n ssh->acceptState >= ACCEPT_SERVER_USERAUTH_SENT;\n}\n#endif\n\n#ifndef NO_WOLFSSH_CLIENT\nINLINE static int IsMessageAllowedClient(WOLFSSH* ssh, byte msg)\n{\n if (msg == MSGID_SERVICE_ACCEPT)\n return ssh->connectState == CONNECT_CLIENT_USERAUTH_REQUEST_SENT;\n if (msg == MSGID_USERAUTH_FAILURE || msg == MSGID_USERAUTH_SUCCESS ||\n msg == MSGID_USERAUTH_BANNER || msg == MSGID_USERAUTH_PK_OK)\n return ssh->connectState >= CONNECT_CLIENT_USERAUTH_SENT &&\n ssh->connectState < CONNECT_SERVER_USERAUTH_ACCEPT_DONE;\n return MSGIDLIMIT_POST_USERAUTH(msg) &&\n ssh->connectState >= CONNECT_SERVER_USERAUTH_ACCEPT_DONE;\n}\n#endif\n\nINLINE static int IsMessageAllowed(WOLFSSH* ssh, byte msg, byte state)\n{\n int allowed = 0;\n if (state == WS_MSG_SEND) {\n /* EOF/window-adjust callers must not consume receive expectations. */\n allowed = !ssh->isKeying;\n if (!allowed)\n ssh->error = WS_REKEYING;\n return allowed;\n }\n if (state != WS_MSG_RECV)\n goto reject;\n\n /* RFC4253 transport notifications may interrupt an expected KEX message. */\n if (msg >= MSGID_DISCONNECT && msg <= MSGID_DEBUG)\n return 1;\n\n /* No RFC8308 negotiation, including during rekey or after authentication. */\n if (msg == MSGID_EXT_INFO)\n goto reject;\n\n if (MSGIDLIMIT_TRANS_ALGO(msg) || MSGIDLIMIT_TRANS_KEX(msg)) {\n if (msg == MSGID_KEXINIT) {\n allowed = !(ssh->isKeying & WOLFSSH_PEER_IS_KEYING);\n }\n else if ((ssh->isKeying & WOLFSSH_PEER_IS_KEYING) &&\n ssh->handshake != NULL &&\n ssh->handshake->expectMsgId != MSGID_NONE &&\n ssh->handshake->expectMsgId == msg) {\n ssh->handshake->expectMsgId = MSGID_NONE;\n return 1;\n }\n if (allowed)\n return 1;\n goto reject;\n }\n\n /* Locally initiated rekey can have old, in-flight peer traffic. Once the\n * peer KEXINIT arrives, only transport/KEX is legal until peer NEWKEYS. */\n if (ssh->isKeying & WOLFSSH_PEER_IS_KEYING)\n goto reject;\n#ifndef NO_WOLFSSH_SERVER\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)\n allowed = IsMessageAllowedServer(ssh, msg);\n#endif\n#ifndef NO_WOLFSSH_CLIENT\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_CLIENT)\n allowed = IsMessageAllowedClient(ssh, msg);\n#endif\n if (allowed)\n return 1;\nreject:\n ssh->error = WS_MSGID_NOT_ALLOWED_E;\n return 0;\n}\n\n\nstatic const char cannedKexAlgoNames[] =\n#if !defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256)\n \"ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org,\"\n#endif\n#ifndef WOLFSSH_NO_CURVE25519_SHA256\n \"curve25519-sha256,\"\n#endif\n#if !defined(WOLFSSH_NO_ECDH_SHA2_NISTP521)\n"
|
||||
},
|
||||
{
|
||||
"old": "#else\n ssh->rfd = -1; /* set to invalid */\n ssh->wfd = -1; /* set to invalid */\n#endif\n ssh->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */\n ssh->ioWriteCtx = &ssh->wfd; /* set */\n ssh->highwaterMark = ctx->highwaterMark;\n ssh->highwaterCtx = (void*)ssh;\n ssh->reqSuccessCtx = (void*)ssh;\n ssh->fs = NULL;\n ssh->acceptState = ACCEPT_BEGIN;\n ssh->clientState = CLIENT_BEGIN;\n ssh->isKeying = 1;\n ssh->authId = ID_USERAUTH_PUBLICKEY;\n ssh->supportedAuth[0] = ID_USERAUTH_PUBLICKEY;\n ssh->supportedAuth[1] = ID_USERAUTH_PASSWORD;\n ssh->supportedAuth[2] = ID_USERAUTH_KEYBOARD;\n ssh->supportedAuth[3] = ID_NONE; /* ID_NONE is treated as empty slot */\n ssh->nextChannel = DEFAULT_NEXT_CHANNEL;\n ssh->blockSz = MIN_BLOCK_SZ;\n ssh->encryptId = ID_NONE;\n ssh->macId = ID_NONE;\n ssh->peerBlockSz = MIN_BLOCK_SZ;\n ssh->rng = rng;\n ssh->kSz = (word32)sizeof(ssh->k);\n",
|
||||
"new": "#else\n ssh->rfd = -1; /* set to invalid */\n ssh->wfd = -1; /* set to invalid */\n#endif\n ssh->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */\n ssh->ioWriteCtx = &ssh->wfd; /* set */\n ssh->highwaterMark = ctx->highwaterMark;\n ssh->highwaterCtx = (void*)ssh;\n ssh->reqSuccessCtx = (void*)ssh;\n ssh->fs = NULL;\n ssh->acceptState = ACCEPT_BEGIN;\n ssh->clientState = CLIENT_BEGIN;\n ssh->isKeying = 0; /* initial state of not keying yet */\n ssh->authId = ID_USERAUTH_PUBLICKEY;\n ssh->supportedAuth[0] = ID_USERAUTH_PUBLICKEY;\n ssh->supportedAuth[1] = ID_USERAUTH_PASSWORD;\n ssh->supportedAuth[2] = ID_USERAUTH_KEYBOARD;\n ssh->supportedAuth[3] = ID_NONE; /* ID_NONE is treated as empty slot */\n ssh->nextChannel = DEFAULT_NEXT_CHANNEL;\n ssh->blockSz = MIN_BLOCK_SZ;\n ssh->encryptId = ID_NONE;\n ssh->macId = ID_NONE;\n ssh->peerBlockSz = MIN_BLOCK_SZ;\n ssh->rng = rng;\n ssh->kSz = (word32)sizeof(ssh->k);\n"
|
||||
},
|
||||
{
|
||||
"old": " word32 cannedAlgoNamesSz;\n word32 skipSz = 0;\n word32 begin;\n\n WLOG(WS_LOG_DEBUG, \"Entering DoKexInit()\");\n\n if (ssh == NULL || ssh->ctx == NULL ||\n buf == NULL || len == 0 || idx == NULL) {\n\n ret = WS_BAD_ARGUMENT;\n }\n\n /*\n * I don't need to save what the client sends here. I should decode\n * each list into a local array of IDs, and pick the one the peer is\n * using that's on my known list, or verify that the one the peer can\n * support the other direction is on my known list. All I need to do\n * is save the actual values.\n */\n\n if (ret == WS_SUCCESS) {\n if (ssh->handshake == NULL) {\n ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);\n if (ssh->handshake == NULL) {\n WLOG(WS_LOG_DEBUG, \"Couldn't allocate handshake info\");\n ret = WS_MEMORY_E;\n }\n }\n }\n\n if (ret == WS_SUCCESS) {\n begin = *idx;\n side = ssh->ctx->side;\n",
|
||||
"new": " word32 cannedAlgoNamesSz;\n word32 skipSz = 0;\n word32 begin;\n\n WLOG(WS_LOG_DEBUG, \"Entering DoKexInit()\");\n\n if (ssh == NULL || ssh->ctx == NULL ||\n buf == NULL || len == 0 || idx == NULL) {\n\n ret = WS_BAD_ARGUMENT;\n }\n\n if (ret == WS_SUCCESS) {\n /* Check if already in process of keying and error out if so. */\n if (ssh->isKeying & WOLFSSH_PEER_IS_KEYING) {\n WLOG(WS_LOG_ERROR,\n \"Already in keying process and got KEX init\");\n ret = WS_INVALID_STATE_E;\n }\n }\n\n /*\n * I don't need to save what the client sends here. I should decode\n * each list into a local array of IDs, and pick the one the peer is\n * using that's on my known list, or verify that the one the peer can\n * support the other direction is on my known list. All I need to do\n * is save the actual values.\n */\n\n if (ret == WS_SUCCESS) {\n /* Set peer is keying flag after receiving SSH_MSG_KEX_INIT */\n ssh->isKeying |= WOLFSSH_PEER_IS_KEYING;\n if (ssh->handshake == NULL) {\n ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);\n if (ssh->handshake == NULL) {\n WLOG(WS_LOG_DEBUG, \"Couldn't allocate handshake info\");\n ret = WS_MEMORY_E;\n }\n }\n }\n\n if (ret == WS_SUCCESS) {\n begin = *idx;\n side = ssh->ctx->side;\n"
|
||||
},
|
||||
{
|
||||
"old": " (const byte*)ssh->algoListKex, cannedAlgoNamesSz);\n }\n if (ret == WS_SUCCESS) {\n ssh->handshake->kexIdGuess = list[0];\n algoId = MatchIdLists(side, list, listSz,\n cannedList, cannedListSz);\n if (algoId == ID_UNKNOWN) {\n WLOG(WS_LOG_DEBUG, \"Unable to negotiate KEX Algo\");\n ret = WS_MATCH_KEX_ALGO_E;\n }\n }\n if (ret == WS_SUCCESS) {\n ssh->kexId = ssh->handshake->kexId = algoId;\n ssh->handshake->kexHashId = HashForId(algoId);\n }\n /* Extension Info Flag */\n if (ret == WS_SUCCESS) {\n /* Only checking for this is we are server. Our client does\n * not have anything to say to a server, yet. */\n if (side == WOLFSSH_ENDPOINT_SERVER) {\n byte extInfo;\n\n /* Match the client accepts extInfo. */\n algoId = ID_EXTINFO_C;\n extInfo = MatchIdLists(side, list, listSz, &algoId, 1);\n ssh->sendExtInfo = extInfo == algoId;\n }\n }\n\n /* Server Host Key Algorithms */\n if (ret == WS_SUCCESS) {\n WLOG(WS_LOG_DEBUG, \"DKI: Server Host Key Algorithms\");\n listSz = (word32)sizeof(list);\n ret = GetNameList(list, &listSz, buf, len, &begin);\n }\n if (ret == WS_SUCCESS) {\n if (side == WOLFSSH_ENDPOINT_SERVER && !ssh->algoListKey) {\n cannedListSz = ssh->ctx->publicKeyAlgoCount;\n WMEMCPY(cannedList, ssh->ctx->publicKeyAlgo, cannedListSz);\n }\n",
|
||||
"new": " (const byte*)ssh->algoListKex, cannedAlgoNamesSz);\n }\n if (ret == WS_SUCCESS) {\n ssh->handshake->kexIdGuess = list[0];\n algoId = MatchIdLists(side, list, listSz,\n cannedList, cannedListSz);\n if (algoId == ID_UNKNOWN) {\n WLOG(WS_LOG_DEBUG, \"Unable to negotiate KEX Algo\");\n ret = WS_MATCH_KEX_ALGO_E;\n }\n }\n if (ret == WS_SUCCESS) {\n /* The reviewed project profile has only these two KEX algorithms.\n * Do not silently enable an untested GEX/PQ continuation. */\n if (algoId != ID_CURVE25519_SHA256 && algoId != ID_ECDH_SHA2_NISTP256)\n ret = WS_MATCH_KEX_ALGO_E;\n ssh->kexId = ssh->handshake->kexId = algoId;\n ssh->handshake->kexHashId = HashForId(algoId);\n }\n /* RFC8308 is optional. This profile never sends EXT_INFO, including\n * after a nonblocking NEWKEYS send or on subsequent rekeys. */\n ssh->sendExtInfo = 0;\n\n /* Server Host Key Algorithms */\n if (ret == WS_SUCCESS) {\n WLOG(WS_LOG_DEBUG, \"DKI: Server Host Key Algorithms\");\n listSz = (word32)sizeof(list);\n ret = GetNameList(list, &listSz, buf, len, &begin);\n }\n if (ret == WS_SUCCESS) {\n if (side == WOLFSSH_ENDPOINT_SERVER && !ssh->algoListKey) {\n cannedListSz = ssh->ctx->publicKeyAlgoCount;\n WMEMCPY(cannedList, ssh->ctx->publicKeyAlgo, cannedListSz);\n }\n"
|
||||
},
|
||||
{
|
||||
"old": " WLOG(WS_LOG_DEBUG, \"DKI: For Future Use\");\n ret = GetUint32(&skipSz, buf, len, &begin);\n if (ret == WS_SUCCESS)\n begin += skipSz;\n }\n\n if (ret == WS_SUCCESS) {\n wc_HashAlg* hash = &ssh->handshake->kexHash;\n enum wc_HashType hashId = (enum wc_HashType)ssh->handshake->kexHashId;\n byte scratchLen[LENGTH_SZ];\n word32 strSz = 0;\n\n if (!ssh->isKeying) {\n WLOG(WS_LOG_DEBUG, \"Keying initiated\");\n ret = SendKexInit(ssh);\n }\n\n /* account for possible want write case from SendKexInit */\n if (ret == WS_SUCCESS || ret == WS_WANT_WRITE)\n ret = wc_HashInit(hash, hashId);\n\n if (ret == WS_SUCCESS) {\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {\n ret = HashUpdate(hash, hashId,\n ssh->peerProtoId, ssh->peerProtoIdSz);\n",
|
||||
"new": " WLOG(WS_LOG_DEBUG, \"DKI: For Future Use\");\n ret = GetUint32(&skipSz, buf, len, &begin);\n if (ret == WS_SUCCESS)\n begin += skipSz;\n }\n\n if (ret == WS_SUCCESS) {\n wc_HashAlg* hash = &ssh->handshake->kexHash;\n enum wc_HashType hashId = (enum wc_HashType)ssh->handshake->kexHashId;\n byte scratchLen[LENGTH_SZ];\n word32 strSz = 0;\n\n /* respond with KEX Init message if not having initiated the keying */\n if ((ssh->isKeying & WOLFSSH_SELF_IS_KEYING) == 0) {\n WLOG(WS_LOG_DEBUG, \"Keying initiated\");\n ret = SendKexInit(ssh);\n }\n\n /* account for possible want write case from SendKexInit */\n if (ret == WS_SUCCESS || ret == WS_WANT_WRITE)\n ret = wc_HashInit(hash, hashId);\n\n if (ret == WS_SUCCESS) {\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {\n ret = HashUpdate(hash, hashId,\n ssh->peerProtoId, ssh->peerProtoIdSz);\n"
|
||||
},
|
||||
{
|
||||
"old": "\n if (ret == WS_SUCCESS)\n ret = HashUpdate(hash, hashId, buf, len);\n\n if (ret == WS_SUCCESS) {\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)\n ret = HashUpdate(hash, hashId,\n ssh->handshake->kexInit, ssh->handshake->kexInitSz);\n }\n\n if (ret == WS_SUCCESS) {\n *idx = begin;\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)\n ssh->clientState = CLIENT_KEXINIT_DONE;\n else\n ssh->serverState = SERVER_KEXINIT_DONE;\n\n /* Propagate potential want write case from SendKexInit. */\n if (ssh->error != 0)\n ret = ssh->error;\n }\n }\n WLOG(WS_LOG_DEBUG, \"Leaving DoKexInit(), ret = %d\", ret);\n return ret;\n}\n\n",
|
||||
"new": "\n if (ret == WS_SUCCESS)\n ret = HashUpdate(hash, hashId, buf, len);\n\n if (ret == WS_SUCCESS) {\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)\n ret = HashUpdate(hash, hashId,\n ssh->handshake->kexInit, ssh->handshake->kexInitSz);\n }\n\n if (ret == WS_SUCCESS) {\n *idx = begin;\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {\n ssh->handshake->expectMsgId = MSGID_KEXDH_INIT;\n ssh->clientState = CLIENT_KEXINIT_DONE;\n }\n else\n ssh->serverState = SERVER_KEXINIT_DONE;\n\n /* Propagate potential want write case from SendKexInit. */\n if (ssh->error != 0)\n ret = ssh->error;\n }\n }\n WLOG(WS_LOG_DEBUG, \"Leaving DoKexInit(), ret = %d\", ret);\n return ret;\n}\n\n"
|
||||
},
|
||||
{
|
||||
"old": "\n if (ssh == NULL || ssh->handshake == NULL || buf == NULL || len == 0 ||\n idx == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n if (ssh->handshake->kexPacketFollows\n && ssh->handshake->kexIdGuess != ssh->handshake->kexId) {\n\n /* skip this message. */\n WLOG(WS_LOG_DEBUG, \"Skipping the client's KEX init function.\");\n ssh->handshake->kexPacketFollows = 0;\n *idx += len;\n return WS_SUCCESS;\n }\n }\n\n if (ret == WS_SUCCESS) {\n begin = *idx;\n ret = GetUint32(&eSz, buf, len, &begin);\n }\n\n if (ret == WS_SUCCESS) {\n /* Validate eSz */\n",
|
||||
"new": "\n if (ssh == NULL || ssh->handshake == NULL || buf == NULL || len == 0 ||\n idx == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n if (ssh->handshake->kexPacketFollows\n && ssh->handshake->kexIdGuess != ssh->handshake->kexId) {\n\n /* skip this message. */\n WLOG(WS_LOG_DEBUG, \"Skipping the client's KEX init function.\");\n ssh->handshake->kexPacketFollows = 0;\n ssh->handshake->expectMsgId = MSGID_KEXDH_INIT;\n *idx += len;\n return WS_SUCCESS;\n }\n }\n\n if (ret == WS_SUCCESS) {\n begin = *idx;\n ret = GetUint32(&eSz, buf, len, &begin);\n }\n\n if (ret == WS_SUCCESS) {\n /* Validate eSz */\n"
|
||||
},
|
||||
{
|
||||
"old": " ret = WS_INVALID_ALGO_ID;\n }\n }\n }\n FreePubKey(sigKeyBlock_ptr);\n }\n\n if (ret == WS_SUCCESS) {\n /* If we aren't using EccKyber, use padding. */\n ret = GenerateKeys(ssh, hashId, !ssh->handshake->useEccKyber);\n }\n\n if (ret == WS_SUCCESS)\n ret = SendNewKeys(ssh);\n\n if (sigKeyBlock_ptr)\n WFREE(sigKeyBlock_ptr, ssh->ctx->heap, DYNTYPE_PRIVKEY);\n WLOG(WS_LOG_DEBUG, \"Leaving DoKexDhReply(), ret = %d\", ret);\n return ret;\n}\n\n\nstatic int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)\n{\n int ret = WS_SUCCESS;\n\n WOLFSSH_UNUSED(buf);\n WOLFSSH_UNUSED(len);\n WOLFSSH_UNUSED(idx);\n\n if (ssh == NULL || ssh->handshake == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n ssh->peerEncryptId = ssh->handshake->encryptId;\n ssh->peerMacId = ssh->handshake->macId;\n ssh->peerBlockSz = ssh->handshake->blockSz;\n ssh->peerMacSz = ssh->handshake->macSz;\n ssh->peerAeadMode = ssh->handshake->aeadMode;\n WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));\n\n switch (ssh->peerEncryptId) {\n case ID_NONE:\n WLOG(WS_LOG_DEBUG, \"DNK: peer using cipher none\");\n",
|
||||
"new": " ret = WS_INVALID_ALGO_ID;\n }\n }\n }\n FreePubKey(sigKeyBlock_ptr);\n }\n\n if (ret == WS_SUCCESS) {\n /* If we aren't using EccKyber, use padding. */\n ret = GenerateKeys(ssh, hashId, !ssh->handshake->useEccKyber);\n }\n\n if (ret == WS_SUCCESS) {\n ssh->handshake->expectMsgId = MSGID_NEWKEYS;\n WLOG_EXPECT_MSGID(ssh->handshake->expectMsgId);\n ret = SendNewKeys(ssh);\n }\n\n if (sigKeyBlock_ptr)\n WFREE(sigKeyBlock_ptr, ssh->ctx->heap, DYNTYPE_PRIVKEY);\n WLOG(WS_LOG_DEBUG, \"Leaving DoKexDhReply(), ret = %d\", ret);\n return ret;\n}\n\n\nstatic int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)\n{\n int ret = WS_SUCCESS;\n\n WOLFSSH_UNUSED(buf);\n WOLFSSH_UNUSED(len);\n WOLFSSH_UNUSED(idx);\n\n if (ssh == NULL || ssh->handshake == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n if ((ssh->isKeying & WOLFSSH_SELF_IS_KEYING) ||\n !(ssh->isKeying & WOLFSSH_PEER_IS_KEYING)) {\n WLOG(WS_LOG_ERROR, \"Keying failed\");\n ret = WS_INVALID_STATE_E;\n }\n }\n\n if (ret == WS_SUCCESS) {\n ssh->peerEncryptId = ssh->handshake->encryptId;\n ssh->peerMacId = ssh->handshake->macId;\n ssh->peerBlockSz = ssh->handshake->blockSz;\n ssh->peerMacSz = ssh->handshake->macSz;\n ssh->peerAeadMode = ssh->handshake->aeadMode;\n WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));\n\n switch (ssh->peerEncryptId) {\n case ID_NONE:\n WLOG(WS_LOG_DEBUG, \"DNK: peer using cipher none\");\n"
|
||||
},
|
||||
{
|
||||
"old": " break;\n }\n\n if (ret == 0)\n ret = WS_SUCCESS;\n else\n ret = WS_CRYPTO_FAILED;\n }\n\n if (ret == WS_SUCCESS) {\n ssh->rxCount = 0;\n ssh->highwaterFlag = 0;\n ssh->isKeying = 0;\n HandshakeInfoFree(ssh->handshake, ssh->ctx->heap);\n ssh->handshake = NULL;\n WLOG(WS_LOG_DEBUG, \"Keying completed\");\n\n if (ssh->ctx->keyingCompletionCb)\n ssh->ctx->keyingCompletionCb(ssh->keyingCompletionCtx);\n }\n\n return ret;\n}\n\n\n#ifndef WOLFSSH_NO_DH_GEX_SHA256\nstatic int DoKexDhGexRequest(WOLFSSH* ssh,\n byte* buf, word32 len, word32* idx)\n{\n",
|
||||
"new": " break;\n }\n\n if (ret == 0)\n ret = WS_SUCCESS;\n else\n ret = WS_CRYPTO_FAILED;\n }\n\n if (ret == WS_SUCCESS) {\n ssh->rxCount = 0;\n ssh->highwaterFlag = 0;\n\n /* Clear peer is keying flag */\n ssh->isKeying &= ~WOLFSSH_PEER_IS_KEYING;\n HandshakeInfoFree(ssh->handshake, ssh->ctx->heap);\n ssh->handshake = NULL;\n WLOG(WS_LOG_DEBUG, \"Keying completed\");\n if (ssh->ctx->keyingCompletionCb)\n ssh->ctx->keyingCompletionCb(ssh->keyingCompletionCtx);\n }\n\n return ret;\n}\n\n\n#ifndef WOLFSSH_NO_DH_GEX_SHA256\nstatic int DoKexDhGexRequest(WOLFSSH* ssh,\n byte* buf, word32 len, word32* idx)\n{\n"
|
||||
},
|
||||
{
|
||||
"old": "\n msg = buf[idx++];\n /* At this point, payload starts at \"buf + idx\". */\n\n /* sanity check on payloadSz. Uses \"or\" condition because of the case when\n * adding idx to payloadSz causes it to overflow.\n */\n if ((ssh->inputBuffer.bufferSz < payloadSz + idx) ||\n (payloadSz + idx < payloadSz)) {\n return WS_OVERFLOW_E;\n }\n\n if (!IsMessageAllowed(ssh, msg)) {\n return WS_MSGID_NOT_ALLOWED_E;\n }\n\n switch (msg) {\n\n case MSGID_DISCONNECT:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_DISCONNECT\");\n ret = DoDisconnect(ssh, buf + idx, payloadSz, &payloadIdx);\n break;\n\n case MSGID_IGNORE:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_IGNORE\");\n",
|
||||
"new": "\n msg = buf[idx++];\n /* At this point, payload starts at \"buf + idx\". */\n\n /* sanity check on payloadSz. Uses \"or\" condition because of the case when\n * adding idx to payloadSz causes it to overflow.\n */\n if ((ssh->inputBuffer.bufferSz < payloadSz + idx) ||\n (payloadSz + idx < payloadSz)) {\n return WS_OVERFLOW_E;\n }\n\n if (!IsMessageAllowed(ssh, msg, WS_MSG_RECV)) {\n return WS_MSGID_NOT_ALLOWED_E;\n }\n\n switch (msg) {\n\n case MSGID_DISCONNECT:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_DISCONNECT\");\n ret = DoDisconnect(ssh, buf + idx, payloadSz, &payloadIdx);\n break;\n\n case MSGID_IGNORE:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_IGNORE\");\n"
|
||||
},
|
||||
{
|
||||
"old": " WLOG(WS_LOG_DEBUG, \"Decoding MSGID_DEBUG\");\n ret = DoDebug(ssh, buf + idx, payloadSz, &payloadIdx);\n break;\n\n case MSGID_EXT_INFO:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_EXT_INFO\");\n ret = DoExtInfo(ssh, buf + idx, payloadSz, &payloadIdx);\n break;\n\n case MSGID_KEXINIT:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_KEXINIT\");\n ret = DoKexInit(ssh, buf + idx, payloadSz, &payloadIdx);\n if (ssh->isKeying == 1 &&\n ssh->connectState == CONNECT_SERVER_CHANNEL_REQUEST_DONE) {\n if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {\n#if !defined(WOLFSSH_NO_DH) && !defined(WOLFSSH_NO_DH_GEX_SHA256)\n ssh->error = SendKexDhGexRequest(ssh);\n#endif\n }\n else\n ssh->error = SendKexDhInit(ssh);\n }\n break;\n\n case MSGID_NEWKEYS:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_NEWKEYS\");\n",
|
||||
"new": " WLOG(WS_LOG_DEBUG, \"Decoding MSGID_DEBUG\");\n ret = DoDebug(ssh, buf + idx, payloadSz, &payloadIdx);\n break;\n\n case MSGID_EXT_INFO:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_EXT_INFO\");\n ret = DoExtInfo(ssh, buf + idx, payloadSz, &payloadIdx);\n break;\n\n case MSGID_KEXINIT:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_KEXINIT\");\n ret = DoKexInit(ssh, buf + idx, payloadSz, &payloadIdx);\n if ((ret == WS_SUCCESS || ret == WS_WANT_WRITE) &&\n ssh->handshake != NULL && ssh->isKeying &&\n ssh->connectState >= CONNECT_SERVER_CHANNEL_REQUEST_DONE) {\n if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {\n#if !defined(WOLFSSH_NO_DH) && !defined(WOLFSSH_NO_DH_GEX_SHA256)\n ssh->error = SendKexDhGexRequest(ssh);\n#endif\n }\n else\n ssh->error = SendKexDhInit(ssh);\n }\n break;\n\n case MSGID_NEWKEYS:\n WLOG(WS_LOG_DEBUG, \"Decoding MSGID_NEWKEYS\");\n"
|
||||
},
|
||||
{
|
||||
"old": " WLOG(WS_LOG_DEBUG, \"Entering SendKexInit()\");\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS && ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER &&\n ssh->ctx->privateKeyCount == 0) {\n WLOG(WS_LOG_DEBUG, \"Server needs at least one private key\");\n ret = WS_BAD_ARGUMENT;\n }\n\n if (ret == WS_SUCCESS) {\n ssh->isKeying = 1;\n if (ssh->handshake == NULL) {\n ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);\n if (ssh->handshake == NULL) {\n WLOG(WS_LOG_DEBUG, \"Couldn't allocate handshake info\");\n ret = WS_MEMORY_E;\n }\n }\n }\n\n if (ret == WS_SUCCESS) {\n if (!ssh->algoListKey && ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {\n keyAlgoNamesSz = BuildNameList(NULL, 0,\n",
|
||||
"new": " WLOG(WS_LOG_DEBUG, \"Entering SendKexInit()\");\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS && ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER &&\n ssh->ctx->privateKeyCount == 0) {\n WLOG(WS_LOG_DEBUG, \"Server needs at least one private key\");\n ret = WS_BAD_ARGUMENT;\n }\n\n if (ret == WS_SUCCESS) {\n /* Set self is keying flag since we started sending the KEX init msg */\n ssh->isKeying |= WOLFSSH_SELF_IS_KEYING;\n if (ssh->handshake == NULL) {\n ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);\n if (ssh->handshake == NULL) {\n WLOG(WS_LOG_DEBUG, \"Couldn't allocate handshake info\");\n ret = WS_MEMORY_E;\n }\n }\n }\n\n if (ret == WS_SUCCESS) {\n if (!ssh->algoListKey && ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {\n keyAlgoNamesSz = BuildNameList(NULL, 0,\n"
|
||||
},
|
||||
{
|
||||
"old": " if (ret > 0) {\n keyAlgoNamesSz = (word32)ret;\n ret = WS_SUCCESS;\n }\n }\n else {\n ret = WS_MEMORY_E;\n }\n }\n }\n\n if (ret == WS_SUCCESS) {\n if (ssh->ctx->side == WOLFSSH_ENDPOINT_CLIENT) {\n kexAlgoNamesPlus = \",ext-info-c\";\n kexAlgoNamesPlusSz = (word32)WSTRLEN(kexAlgoNamesPlus);\n }\n\n kexAlgoNamesSz = AlgoListSz(ssh->algoListKex);\n encAlgoNamesSz = AlgoListSz(ssh->algoListCipher);\n if (!keyAlgoNames) {\n keyAlgoNamesSz = AlgoListSz(ssh->algoListKey);\n }\n else {\n keyAlgoNamesSz = AlgoListSz(keyAlgoNames);\n }\n macAlgoNamesSz = AlgoListSz(ssh->algoListMac);\n noneNamesSz = AlgoListSz(cannedNoneNames);\n payloadSz = MSG_ID_SZ + COOKIE_SZ + (LENGTH_SZ * 11) + BOOLEAN_SZ +\n + kexAlgoNamesSz + kexAlgoNamesPlusSz + keyAlgoNamesSz\n",
|
||||
"new": " if (ret > 0) {\n keyAlgoNamesSz = (word32)ret;\n ret = WS_SUCCESS;\n }\n }\n else {\n ret = WS_MEMORY_E;\n }\n }\n }\n\n if (ret == WS_SUCCESS) {\n kexAlgoNamesSz = AlgoListSz(ssh->algoListKex);\n encAlgoNamesSz = AlgoListSz(ssh->algoListCipher);\n if (!keyAlgoNames) {\n keyAlgoNamesSz = AlgoListSz(ssh->algoListKey);\n }\n else {\n keyAlgoNamesSz = AlgoListSz(keyAlgoNames);\n }\n macAlgoNamesSz = AlgoListSz(ssh->algoListMac);\n noneNamesSz = AlgoListSz(cannedNoneNames);\n payloadSz = MSG_ID_SZ + COOKIE_SZ + (LENGTH_SZ * 11) + BOOLEAN_SZ +\n + kexAlgoNamesSz + kexAlgoNamesPlusSz + keyAlgoNamesSz\n"
|
||||
},
|
||||
{
|
||||
"old": " }\n\n if (keyAlgoNames) {\n WFREE(keyAlgoNames, ssh->ctx->heap, DYNTYPE_STRING);\n }\n\n if (ret == WS_SUCCESS) {\n /* increase amount to be sent only if BundlePacket will be called */\n ssh->outputBuffer.length = idx;\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS)\n ret = wolfSSH_SendPacket(ssh);\n\n if (ret != WS_WANT_WRITE && ret != WS_SUCCESS)\n PurgePacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexInit(), ret = %d\", ret);\n return ret;\n}\n\n\nstruct wolfSSH_sigKeyBlockFull {\n byte pubKeyId; /* handshake->pubKeyId */\n byte pubKeyFmtId;\n",
|
||||
"new": " }\n\n if (keyAlgoNames) {\n WFREE(keyAlgoNames, ssh->ctx->heap, DYNTYPE_STRING);\n }\n\n if (ret == WS_SUCCESS) {\n /* increase amount to be sent only if BundlePacket will be called */\n ssh->outputBuffer.length = idx;\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS) {\n ret = wolfSSH_SendPacket(ssh);\n }\n\n if (ret != WS_WANT_WRITE && ret != WS_SUCCESS)\n PurgePacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexInit(), ret = %d\", ret);\n return ret;\n}\n\n\nstruct wolfSSH_sigKeyBlockFull {\n byte pubKeyId; /* handshake->pubKeyId */\n byte pubKeyFmtId;\n"
|
||||
},
|
||||
{
|
||||
"old": " sigKeyBlock_ptr->pubKeyName, sigKeyBlock_ptr->pubKeyNameSz);\n idx += sigKeyBlock_ptr->pubKeyNameSz;\n c32toa(sigSz, output + idx);\n idx += LENGTH_SZ;\n WMEMCPY(output + idx, sig_ptr, sigSz);\n idx += sigSz;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS)\n ret = SendNewKeys(ssh);\n\n if (ret == WS_SUCCESS && ssh->sendExtInfo) {\n ret = SendExtInfo(ssh);\n }\n\n if (ret != WS_WANT_WRITE && ret != WS_SUCCESS)\n PurgePacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexDhReply(), ret = %d\", ret);\n if (sigKeyBlock_ptr)\n WFREE(sigKeyBlock_ptr, heap, DYNTYPE_PRIVKEY);\n#ifdef WOLFSSH_SMALL_STACK\n if (f_ptr)\n WFREE(f_ptr, heap, DYNTYPE_BUFFER);\n if (sig_ptr)\n",
|
||||
"new": " sigKeyBlock_ptr->pubKeyName, sigKeyBlock_ptr->pubKeyNameSz);\n idx += sigKeyBlock_ptr->pubKeyNameSz;\n c32toa(sigSz, output + idx);\n idx += LENGTH_SZ;\n WMEMCPY(output + idx, sig_ptr, sigSz);\n idx += sigSz;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS) {\n ssh->handshake->expectMsgId = MSGID_NEWKEYS;\n WLOG_EXPECT_MSGID(ssh->handshake->expectMsgId);\n ret = SendNewKeys(ssh);\n }\n\n if (ret != WS_WANT_WRITE && ret != WS_SUCCESS)\n PurgePacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexDhReply(), ret = %d\", ret);\n if (sigKeyBlock_ptr)\n WFREE(sigKeyBlock_ptr, heap, DYNTYPE_PRIVKEY);\n#ifdef WOLFSSH_SMALL_STACK\n if (f_ptr)\n WFREE(f_ptr, heap, DYNTYPE_BUFFER);\n if (sig_ptr)\n"
|
||||
},
|
||||
{
|
||||
"old": "#endif\n\n default:\n WLOG(WS_LOG_DEBUG, \"SNK: using cipher invalid\");\n ret = WS_INVALID_ALGO_ID;\n }\n }\n\n if (ret == WS_SUCCESS) {\n ssh->txCount = 0;\n }\n\n if (ret == WS_SUCCESS)\n ret = wolfSSH_SendPacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendNewKeys(), ret = %d\", ret);\n return ret;\n}\n\n\n#ifndef WOLFSSH_NO_DH_GEX_SHA256\nint SendKexDhGexRequest(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx = 0;\n word32 payloadSz;\n",
|
||||
"new": "#endif\n\n default:\n WLOG(WS_LOG_DEBUG, \"SNK: using cipher invalid\");\n ret = WS_INVALID_ALGO_ID;\n }\n }\n\n if (ret == WS_SUCCESS) {\n ssh->txCount = 0;\n }\n\n if (ret == WS_SUCCESS) {\n ret = wolfSSH_SendPacket(ssh);\n\n /* Queued NEWKEYS is already bundled with the old keys. A partial\n * write is resumed by SendPacket, never by rebuilding NEWKEYS. */\n if (ret == WS_SUCCESS || ret == WS_WANT_WRITE)\n ssh->isKeying &= ~WOLFSSH_SELF_IS_KEYING;\n }\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendNewKeys(), ret = %d\", ret);\n return ret;\n}\n\n\n#ifndef WOLFSSH_NO_DH_GEX_SHA256\nint SendKexDhGexRequest(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx = 0;\n word32 payloadSz;\n"
|
||||
},
|
||||
{
|
||||
"old": " c32toa(ssh->handshake->dhGexMinSz, output + idx);\n idx += UINT32_SZ;\n c32toa(ssh->handshake->dhGexPreferredSz, output + idx);\n idx += UINT32_SZ;\n c32toa(ssh->handshake->dhGexMaxSz, output + idx);\n idx += UINT32_SZ;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS)\n ret = wolfSSH_SendPacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexDhGexRequest(), ret = %d\", ret);\n return ret;\n}\n\n\nint SendKexDhGexGroup(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx = 0;\n word32 payloadSz;\n const byte* primeGroup = dhPrimeGroup14;\n",
|
||||
"new": " c32toa(ssh->handshake->dhGexMinSz, output + idx);\n idx += UINT32_SZ;\n c32toa(ssh->handshake->dhGexPreferredSz, output + idx);\n idx += UINT32_SZ;\n c32toa(ssh->handshake->dhGexMaxSz, output + idx);\n idx += UINT32_SZ;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS) {\n WLOG_EXPECT_MSGID(MSGID_KEXDH_GEX_GROUP);\n ssh->handshake->expectMsgId = MSGID_KEXDH_GEX_GROUP;\n ret = wolfSSH_SendPacket(ssh);\n }\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexDhGexRequest(), ret = %d\", ret);\n return ret;\n}\n\n\nint SendKexDhGexGroup(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx = 0;\n word32 payloadSz;\n const byte* primeGroup = dhPrimeGroup14;\n"
|
||||
},
|
||||
{
|
||||
"old": "{\n byte* output;\n word32 idx = 0;\n word32 payloadSz;\n#ifndef WOLFSSH_NO_DH\n const byte* primeGroup = NULL;\n word32 primeGroupSz = 0;\n const byte* generator = NULL;\n word32 generatorSz = 0;\n#endif\n int ret = WS_SUCCESS;\n byte msgId = MSGID_KEXDH_INIT;\n byte e[MAX_KEX_KEY_SZ+1]; /* plus 1 in case of padding. */\n word32 eSz = (word32)sizeof(e);\n byte ePad = 0;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendKexDhInit()\");\n\n switch (ssh->handshake->kexId) {\n#ifndef WOLFSSH_NO_DH_GROUP1_SHA1\n case ID_DH_GROUP1_SHA1:\n ssh->handshake->useDh = 1;\n primeGroup = dhPrimeGroup1;\n primeGroupSz = dhPrimeGroup1Sz;\n",
|
||||
"new": "{\n byte* output;\n word32 idx = 0;\n word32 payloadSz;\n#ifndef WOLFSSH_NO_DH\n const byte* primeGroup = NULL;\n word32 primeGroupSz = 0;\n const byte* generator = NULL;\n word32 generatorSz = 0;\n#endif\n int ret = WS_SUCCESS;\n byte msgId = MSGID_KEXDH_INIT;\n byte expectMsgId = MSGID_KEXDH_REPLY;\n byte e[MAX_KEX_KEY_SZ+1]; /* plus 1 in case of padding. */\n word32 eSz = (word32)sizeof(e);\n byte ePad = 0;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendKexDhInit()\");\n\n switch (ssh->handshake->kexId) {\n#ifndef WOLFSSH_NO_DH_GROUP1_SHA1\n case ID_DH_GROUP1_SHA1:\n ssh->handshake->useDh = 1;\n primeGroup = dhPrimeGroup1;\n primeGroupSz = dhPrimeGroup1Sz;\n"
|
||||
},
|
||||
{
|
||||
"old": " generator = dhGenerator;\n generatorSz = dhGeneratorSz;\n break;\n#endif\n#ifndef WOLFSSH_NO_DH_GEX_SHA256\n case ID_DH_GEX_SHA256:\n ssh->handshake->useDh = 1;\n primeGroup = ssh->handshake->primeGroup;\n primeGroupSz = ssh->handshake->primeGroupSz;\n generator = ssh->handshake->generator;\n generatorSz = ssh->handshake->generatorSz;\n msgId = MSGID_KEXDH_GEX_INIT;\n break;\n#endif\n#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256\n case ID_ECDH_SHA2_NISTP256:\n ssh->handshake->useEcc = 1;\n msgId = MSGID_KEXECDH_INIT;\n break;\n#endif\n#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP384\n case ID_ECDH_SHA2_NISTP384:\n ssh->handshake->useEcc = 1;\n msgId = MSGID_KEXECDH_INIT;\n",
|
||||
"new": " generator = dhGenerator;\n generatorSz = dhGeneratorSz;\n break;\n#endif\n#ifndef WOLFSSH_NO_DH_GEX_SHA256\n case ID_DH_GEX_SHA256:\n ssh->handshake->useDh = 1;\n primeGroup = ssh->handshake->primeGroup;\n primeGroupSz = ssh->handshake->primeGroupSz;\n generator = ssh->handshake->generator;\n generatorSz = ssh->handshake->generatorSz;\n msgId = MSGID_KEXDH_GEX_INIT;\n expectMsgId = MSGID_KEXDH_GEX_REPLY;\n break;\n#endif\n#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256\n case ID_ECDH_SHA2_NISTP256:\n ssh->handshake->useEcc = 1;\n msgId = MSGID_KEXECDH_INIT;\n break;\n#endif\n#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP384\n case ID_ECDH_SHA2_NISTP384:\n ssh->handshake->useEcc = 1;\n msgId = MSGID_KEXECDH_INIT;\n"
|
||||
},
|
||||
{
|
||||
"old": " output[idx] = 0;\n idx++;\n }\n\n WMEMCPY(output + idx, e, eSz);\n idx += eSz;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS)\n ret = wolfSSH_SendPacket(ssh);\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexDhInit(), ret = %d\", ret);\n return ret;\n}\n\n\nint SendUnimplemented(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx = 0;\n int ret = WS_SUCCESS;\n\n",
|
||||
"new": " output[idx] = 0;\n idx++;\n }\n\n WMEMCPY(output + idx, e, eSz);\n idx += eSz;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS) {\n WLOG_EXPECT_MSGID(expectMsgId);\n ssh->handshake->expectMsgId = expectMsgId;\n ret = wolfSSH_SendPacket(ssh);\n }\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendKexDhInit(), ret = %d\", ret);\n return ret;\n}\n\n\nint SendUnimplemented(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx = 0;\n int ret = WS_SUCCESS;\n\n"
|
||||
},
|
||||
{
|
||||
"old": " ret = SendUserAuthBanner(ssh);\n\n return ret;\n}\n\n\n#define WS_EXTINFO_EXTENSION_COUNT 1\nstatic const char serverSigAlgsName[] = \"server-sig-algs\";\n\n\nint SendExtInfo(WOLFSSH* ssh)\n{\n byte* output;\n word32 idx;\n word32 keyAlgoNamesSz = 0;\n word32 serverSigAlgsNameSz = 0;\n int ret = WS_SUCCESS;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendExtInfo()\");\n\n if (ssh == NULL) {\n ret = WS_BAD_ARGUMENT;\n }\n\n if (ret == WS_SUCCESS) {\n keyAlgoNamesSz = AlgoListSz(ssh->algoListKeyAccepted);\n serverSigAlgsNameSz = AlgoListSz(serverSigAlgsName);\n ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + (LENGTH_SZ * 2)\n + serverSigAlgsNameSz + keyAlgoNamesSz);\n }\n\n if (ret == WS_SUCCESS) {\n output = ssh->outputBuffer.buffer;\n idx = ssh->outputBuffer.length;\n\n output[idx++] = MSGID_EXT_INFO;\n c32toa(WS_EXTINFO_EXTENSION_COUNT, output + idx);\n idx += UINT32_SZ;\n\n c32toa(serverSigAlgsNameSz, output + idx);\n idx += LENGTH_SZ;\n WMEMCPY(output + idx, serverSigAlgsName, serverSigAlgsNameSz);\n idx += serverSigAlgsNameSz;\n\n c32toa(keyAlgoNamesSz, output + idx);\n idx += LENGTH_SZ;\n WMEMCPY(output + idx, ssh->algoListKeyAccepted, keyAlgoNamesSz);\n idx += keyAlgoNamesSz;\n\n ssh->outputBuffer.length = idx;\n\n ret = BundlePacket(ssh);\n }\n\n if (ret == WS_SUCCESS) {\n ret = wolfSSH_SendPacket(ssh);\n }\n\n WLOG(WS_LOG_DEBUG, \"Leaving SendExtInfo(), ret = %d\", ret);\n return ret;\n}\n\n\n/* Updates the payload size, and maybe loads keys. */\nstatic int PrepareUserAuthRequestPassword(WOLFSSH* ssh, word32* payloadSz,\n const WS_UserAuthData* authData)\n{\n int ret = WS_SUCCESS;\n\n if (ssh == NULL || payloadSz == NULL || authData == NULL)\n ret = WS_BAD_ARGUMENT;\n\n",
|
||||
"new": " ret = SendUserAuthBanner(ssh);\n\n return ret;\n}\n\n\n#define WS_EXTINFO_EXTENSION_COUNT 1\nstatic const char serverSigAlgsName[] = \"server-sig-algs\";\n\n\nint SendExtInfo(WOLFSSH* ssh)\n{\n WOLFSSH_UNUSED(ssh);\n return WS_NOT_COMPILED;\n}\n\n\n/* Updates the payload size, and maybe loads keys. */\nstatic int PrepareUserAuthRequestPassword(WOLFSSH* ssh, word32* payloadSz,\n const WS_UserAuthData* authData)\n{\n int ret = WS_SUCCESS;\n\n if (ssh == NULL || payloadSz == NULL || authData == NULL)\n ret = WS_BAD_ARGUMENT;\n\n"
|
||||
},
|
||||
{
|
||||
"old": "int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId)\n{\n byte* output;\n word32 idx;\n int ret = WS_SUCCESS;\n WOLFSSH_CHANNEL* channel = NULL;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendChannelEof()\");\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;",
|
||||
"new": "int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId)\n{\n byte* output;\n word32 idx;\n int ret = WS_SUCCESS;\n WOLFSSH_CHANNEL* channel = NULL;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendChannelEof()\");\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n if (!IsMessageAllowed(ssh, MSGID_CHANNEL_EOF, WS_MSG_SEND)) {\n ret = WS_MSGID_NOT_ALLOWED_E;\n }\n }"
|
||||
},
|
||||
{
|
||||
"old": " const char* str = \"exit-status\";\n word32 idx;\n word32 strSz = 0;\n int ret = WS_SUCCESS;\n WOLFSSH_CHANNEL* channel = NULL;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendChannelExit(), status = %d\", status);\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);\n if (channel == NULL)\n ret = WS_INVALID_CHANID;\n }\n\n if (ret == WS_SUCCESS) {\n strSz = (word32)WSTRLEN(str);\n ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ + strSz +\n BOOLEAN_SZ + UINT32_SZ);\n }\n\n if (ret == WS_SUCCESS) {\n",
|
||||
"new": " const char* str = \"exit-status\";\n word32 idx;\n word32 strSz = 0;\n int ret = WS_SUCCESS;\n WOLFSSH_CHANNEL* channel = NULL;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendChannelExit(), status = %d\", status);\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n if (!IsMessageAllowed(ssh, MSGID_CHANNEL_REQUEST, WS_MSG_SEND)) {\n ret = WS_MSGID_NOT_ALLOWED_E;\n }\n }\n\n if (ret == WS_SUCCESS) {\n channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);\n if (channel == NULL)\n ret = WS_INVALID_CHANID;\n }\n\n if (ret == WS_SUCCESS) {\n strSz = (word32)WSTRLEN(str);\n ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ + strSz +\n BOOLEAN_SZ + UINT32_SZ);\n }\n\n if (ret == WS_SUCCESS) {\n"
|
||||
},
|
||||
{
|
||||
"old": "int SendChannelWindowAdjust(WOLFSSH* ssh, word32 channelId,\n word32 bytesToAdd)\n{\n byte* output;\n word32 idx;\n int ret = WS_SUCCESS;\n WOLFSSH_CHANNEL* channel;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendChannelWindowAdjust()\");\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);\n if (channel == NULL) {\n WLOG(WS_LOG_DEBUG, \"Invalid channel\");\n ret = WS_INVALID_CHANID;\n }\n if (ret == WS_SUCCESS)\n ret = PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 2));\n\n if (ret == WS_SUCCESS) {\n output = ssh->outputBuffer.buffer;\n idx = ssh->outputBuffer.length;\n",
|
||||
"new": "int SendChannelWindowAdjust(WOLFSSH* ssh, word32 channelId,\n word32 bytesToAdd)\n{\n byte* output;\n word32 idx;\n int ret = WS_SUCCESS;\n WOLFSSH_CHANNEL* channel;\n\n WLOG(WS_LOG_DEBUG, \"Entering SendChannelWindowAdjust()\");\n\n if (ssh == NULL)\n ret = WS_BAD_ARGUMENT;\n\n if (ret == WS_SUCCESS) {\n if (!IsMessageAllowed(ssh, MSGID_CHANNEL_WINDOW_ADJUST, WS_MSG_SEND)) {\n ret = WS_MSGID_NOT_ALLOWED_E;\n }\n }\n\n channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);\n if (channel == NULL) {\n WLOG(WS_LOG_DEBUG, \"Invalid channel\");\n ret = WS_INVALID_CHANID;\n }\n if (ret == WS_SUCCESS)\n ret = PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 2));\n\n if (ret == WS_SUCCESS) {\n output = ssh->outputBuffer.buffer;\n idx = ssh->outputBuffer.length;\n"
|
||||
},
|
||||
{
|
||||
"old": "static const char serverSigAlgsName[] = \"server-sig-algs\";\n",
|
||||
"new": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/ssh.c": {
|
||||
"sha256": "a4f479ff87eea0980ec1ebdf2c7dd090da473780181b695a56799cb9611f4366",
|
||||
"edits": [
|
||||
{
|
||||
"old": " WOLFSSH_BUFFER* inputBuffer;\n\n WLOG(WS_LOG_DEBUG, \"Entering wolfSSH_stream_read()\");\n\n if (ssh == NULL || buf == NULL || bufSz == 0 || ssh->channelList == NULL)\n return WS_BAD_ARGUMENT;\n\n if (ssh->channelList->eofRxd) {\n ssh->error = WS_EOF;\n return WS_ERROR;\n }\n\n inputBuffer = &ssh->channelList->inputBuffer;\n ssh->error = WS_SUCCESS;\n\n if (ret == WS_SUCCESS) {\n WLOG(WS_LOG_DEBUG, \" Stream read index of %u\", inputBuffer->idx);\n WLOG(WS_LOG_DEBUG, \" Stream read ava data %u\", inputBuffer->length);\n while (inputBuffer->length - inputBuffer->idx == 0) {\n WLOG(WS_LOG_DEBUG,\n \"Starting to recieve data at current index of %u\",\n inputBuffer->idx);\n ret = DoReceive(ssh);\n if (ssh->channelList == NULL || ssh->channelList->eofRxd)\n",
|
||||
"new": " WOLFSSH_BUFFER* inputBuffer;\n\n WLOG(WS_LOG_DEBUG, \"Entering wolfSSH_stream_read()\");\n\n if (ssh == NULL || buf == NULL || bufSz == 0 || ssh->channelList == NULL)\n return WS_BAD_ARGUMENT;\n\n if (ssh->channelList->eofRxd) {\n ssh->error = WS_EOF;\n return WS_ERROR;\n }\n\n if (ssh->isKeying) {\n ssh->error = WS_REKEYING;\n return WS_FATAL_ERROR;\n }\n\n inputBuffer = &ssh->channelList->inputBuffer;\n ssh->error = WS_SUCCESS;\n\n if (ret == WS_SUCCESS) {\n WLOG(WS_LOG_DEBUG, \" Stream read index of %u\", inputBuffer->idx);\n WLOG(WS_LOG_DEBUG, \" Stream read ava data %u\", inputBuffer->length);\n while (inputBuffer->length - inputBuffer->idx == 0) {\n WLOG(WS_LOG_DEBUG,\n \"Starting to recieve data at current index of %u\",\n inputBuffer->idx);\n ret = DoReceive(ssh);\n if (ssh->channelList == NULL || ssh->channelList->eofRxd)\n"
|
||||
},
|
||||
{
|
||||
"old": " if (ssh->lastRxId != ssh->channelList->channel) {\n ret = WS_ERROR;\n break;\n }\n else {\n ret = WS_SUCCESS;\n }\n }\n }\n }\n\n /* update internal input buffer based on data read */\n if (ret == WS_SUCCESS) {\n int n;\n\n n = min(bufSz, inputBuffer->length - inputBuffer->idx);\n if (n <= 0)\n ret = WS_BUFFER_E;\n else {\n WMEMCPY(buf, inputBuffer->buffer + inputBuffer->idx, n);\n ret = _UpdateChannelWindow(ssh->channelList);\n if (ret == WS_SUCCESS) {\n inputBuffer->idx += n;\n ret = n;\n }\n",
|
||||
"new": " if (ssh->lastRxId != ssh->channelList->channel) {\n ret = WS_ERROR;\n break;\n }\n else {\n ret = WS_SUCCESS;\n }\n }\n }\n }\n\n /* update internal input buffer based on data read */\n if (ret == WS_SUCCESS && !ssh->isKeying) {\n int n;\n\n n = min(bufSz, inputBuffer->length - inputBuffer->idx);\n if (n <= 0)\n ret = WS_BUFFER_E;\n else {\n WMEMCPY(buf, inputBuffer->buffer + inputBuffer->idx, n);\n ret = _UpdateChannelWindow(ssh->channelList);\n if (ret == WS_SUCCESS) {\n inputBuffer->idx += n;\n ret = n;\n }\n"
|
||||
},
|
||||
{
|
||||
"old": "\nint wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz)\n{\n int bytesTxd = 0;\n\n WLOG(WS_LOG_DEBUG, \"Entering wolfSSH_stream_send()\");\n\n if (ssh == NULL || buf == NULL || ssh->channelList == NULL)\n return WS_BAD_ARGUMENT;\n\n if (ssh->isKeying) {\n ssh->error = WS_REKEYING;\n return WS_REKEYING;\n }\n\n bytesTxd = SendChannelData(ssh, ssh->channelList->channel, buf, bufSz);\n\n WLOG(WS_LOG_DEBUG, \"Leaving wolfSSH_stream_send(), txd = %d\", bytesTxd);\n return bytesTxd;\n}\n\n\nint wolfSSH_ChannelIdSend(WOLFSSH* ssh, word32 channelId,\n byte* buf, word32 bufSz)\n{\n",
|
||||
"new": "\nint wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz)\n{\n int bytesTxd = 0;\n\n WLOG(WS_LOG_DEBUG, \"Entering wolfSSH_stream_send()\");\n\n if (ssh == NULL || buf == NULL || ssh->channelList == NULL)\n return WS_BAD_ARGUMENT;\n\n if (ssh->isKeying) {\n ssh->error = WS_REKEYING;\n return WS_FATAL_ERROR;\n }\n\n bytesTxd = SendChannelData(ssh, ssh->channelList->channel, buf, bufSz);\n\n WLOG(WS_LOG_DEBUG, \"Leaving wolfSSH_stream_send(), txd = %d\", bytesTxd);\n return bytesTxd;\n}\n\n\nint wolfSSH_ChannelIdSend(WOLFSSH* ssh, word32 channelId,\n byte* buf, word32 bufSz)\n{\n"
|
||||
},
|
||||
{
|
||||
"old": " return bufSz;\n}\n\n\nint wolfSSH_ChannelRead(WOLFSSH_CHANNEL* channel, byte* buf, word32 bufSz)\n{\n\n WLOG(WS_LOG_DEBUG, \"Entering wolfSSH_ChannelRead()\");\n\n if (channel == NULL || buf == NULL || bufSz == 0)\n return WS_BAD_ARGUMENT;\n\n bufSz = _ChannelRead(channel, buf, bufSz);\n\n WLOG(WS_LOG_DEBUG, \"Leaving wolfSSH_ChannelRead(), bytesRxd = %d\",\n bufSz);\n return bufSz;\n}\n\n\nint wolfSSH_ChannelSend(WOLFSSH_CHANNEL* channel,\n const byte* buf, word32 bufSz)\n{\n int bytesTxd = 0;\n",
|
||||
"new": " return bufSz;\n}\n\n\nint wolfSSH_ChannelRead(WOLFSSH_CHANNEL* channel, byte* buf, word32 bufSz)\n{\n\n WLOG(WS_LOG_DEBUG, \"Entering wolfSSH_ChannelRead()\");\n\n if (channel == NULL || buf == NULL || bufSz == 0)\n return WS_BAD_ARGUMENT;\n\n if (channel->ssh->isKeying) {\n channel->ssh->error = WS_REKEYING;\n return WS_REKEYING;\n }\n\n bufSz = _ChannelRead(channel, buf, bufSz);\n\n WLOG(WS_LOG_DEBUG, \"Leaving wolfSSH_ChannelRead(), bytesRxd = %d\",\n bufSz);\n return bufSz;\n}\n\n\nint wolfSSH_ChannelSend(WOLFSSH_CHANNEL* channel,\n const byte* buf, word32 bufSz)\n{\n int bytesTxd = 0;\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"wolfssh/internal.h": {
|
||||
"sha256": "8e417149a68f8a6c0506957adf014b3e6c1727a723536826ce5fb0c9e1f1aba3",
|
||||
"edits": [
|
||||
{
|
||||
"old": " #define WOLFSSH_MAX_FILE_SIZE (1024ul * 1024ul * 4)\n#endif\n#ifndef WOLFSSH_MAX_PVT_KEYS\n #define WOLFSSH_MAX_PVT_KEYS 8\n#endif\n#ifndef WOLFSSH_MAX_PUB_KEY_ALGO\n #define WOLFSSH_MAX_PUB_KEY_ALGO (WOLFSSH_MAX_PVT_KEYS + 2)\n#endif\n#ifndef WOLFSSH_KEY_QUANTITY_REQ\n #define WOLFSSH_KEY_QUANTITY_REQ 1\n#endif\n\n\nWOLFSSH_LOCAL byte NameToId(const char* name, word32 nameSz);\nWOLFSSH_LOCAL const char* IdToName(byte id);\nWOLFSSH_LOCAL const char* NameByIndexType(byte type, word32* index);\n\n\n/* For cases when openssl coexist is used */\n#ifdef WC_NO_COMPAT_AES_BLOCK_SIZE\n #define AES_BLOCK_SIZE WC_AES_BLOCK_SIZE\n#endif\n\n#define STATIC_BUFFER_LEN AES_BLOCK_SIZE\n",
|
||||
"new": " #define WOLFSSH_MAX_FILE_SIZE (1024ul * 1024ul * 4)\n#endif\n#ifndef WOLFSSH_MAX_PVT_KEYS\n #define WOLFSSH_MAX_PVT_KEYS 8\n#endif\n#ifndef WOLFSSH_MAX_PUB_KEY_ALGO\n #define WOLFSSH_MAX_PUB_KEY_ALGO (WOLFSSH_MAX_PVT_KEYS + 2)\n#endif\n#ifndef WOLFSSH_KEY_QUANTITY_REQ\n #define WOLFSSH_KEY_QUANTITY_REQ 1\n#endif\n\n/* Keep track of keying state for both sides of the connection.\n * WOLFSSH_SELF_IS_KEYING gets set on sending KEX init and\n * WOLFSSH_PEER_IS_KEYING gets set on receiving KEX init */\n#define WOLFSSH_PEER_IS_KEYING 0x01\n#define WOLFSSH_SELF_IS_KEYING 0x02\n\nWOLFSSH_LOCAL byte NameToId(const char* name, word32 nameSz);\nWOLFSSH_LOCAL const char* IdToName(byte id);\nWOLFSSH_LOCAL const char* NameByIndexType(byte type, word32* index);\n\n\n/* For cases when openssl coexist is used */\n#ifdef WC_NO_COMPAT_AES_BLOCK_SIZE\n #define AES_BLOCK_SIZE WC_AES_BLOCK_SIZE\n#endif\n\n#define STATIC_BUFFER_LEN AES_BLOCK_SIZE\n"
|
||||
},
|
||||
{
|
||||
"old": "\ntypedef struct Keys {\n byte iv[AES_BLOCK_SIZE];\n byte ivSz;\n byte encKey[AES_256_KEY_SIZE];\n byte encKeySz;\n byte macKey[MAX_HMAC_SZ];\n byte macKeySz;\n} Keys;\n\n\ntypedef struct HandshakeInfo {\n byte kexId;\n byte kexIdGuess;\n byte kexHashId;\n byte pubKeyId;\n byte encryptId;\n byte macId;\n byte kexPacketFollows;\n byte aeadMode;\n\n byte blockSz;\n byte macSz;\n\n",
|
||||
"new": "\ntypedef struct Keys {\n byte iv[AES_BLOCK_SIZE];\n byte ivSz;\n byte encKey[AES_256_KEY_SIZE];\n byte encKeySz;\n byte macKey[MAX_HMAC_SZ];\n byte macKeySz;\n} Keys;\n\n\ntypedef struct HandshakeInfo {\n byte expectMsgId;\n byte kexId;\n byte kexIdGuess;\n byte kexHashId;\n byte pubKeyId;\n byte encryptId;\n byte macId;\n byte kexPacketFollows;\n byte aeadMode;\n\n byte blockSz;\n byte macSz;\n\n"
|
||||
},
|
||||
{
|
||||
"old": " char* userName;\n word32 userNameSz;\n char* password;\n word32 passwordSz;\n byte* pkBlob;\n word32 pkBlobSz;\n byte* peerProtoId; /* Save for rekey */\n word32 peerProtoIdSz;\n void* publicKeyCheckCtx;\n byte sendTerminalRequest;\n byte userAuthPkDone;\n byte sendExtInfo;\n byte* peerSigId;\n word32 peerSigIdSz;\n\n#ifdef USE_WINDOWS_API\n word32 defaultAttr; /* default windows attributes */\n byte defaultAttrSet;\n byte escBuf[WOLFSSL_MAX_ESCBUF]; /* console codes are about 3 byte and\n * have max arguments of 16 */\n byte escBufSz;\n byte escState; /* current console translation state */\n#endif\n#ifdef WOLFSSH_SFTP\n",
|
||||
"new": " char* userName;\n word32 userNameSz;\n char* password;\n word32 passwordSz;\n byte* pkBlob;\n word32 pkBlobSz;\n byte* peerProtoId; /* Save for rekey */\n word32 peerProtoIdSz;\n void* publicKeyCheckCtx;\n byte sendTerminalRequest;\n byte userAuthPkDone;\n byte sendExtInfo;\n byte extInfoSent; /* track if the ext info has already been sent */\n byte* peerSigId;\n word32 peerSigIdSz;\n\n#ifdef USE_WINDOWS_API\n word32 defaultAttr; /* default windows attributes */\n byte defaultAttrSet;\n byte escBuf[WOLFSSL_MAX_ESCBUF]; /* console codes are about 3 byte and\n * have max arguments of 16 */\n byte escBufSz;\n byte escState; /* current console translation state */\n#endif\n#ifdef WOLFSSH_SFTP\n"
|
||||
},
|
||||
{
|
||||
"old": "};\n\n\nenum ProcessReplyStates {\n PROCESS_INIT,\n PROCESS_PACKET_LENGTH,\n PROCESS_PACKET_FINISH,\n PROCESS_PACKET\n};\n\n\nenum WS_MessageIds {\n MSGID_DISCONNECT = 1,\n MSGID_IGNORE = 2,\n MSGID_UNIMPLEMENTED = 3,\n MSGID_DEBUG = 4,\n MSGID_SERVICE_REQUEST = 5,\n MSGID_SERVICE_ACCEPT = 6,\n MSGID_EXT_INFO = 7,\n\n MSGID_KEXINIT = 20,\n MSGID_NEWKEYS = 21,\n\n MSGID_KEXDH_INIT = 30,\n",
|
||||
"new": "};\n\n\nenum ProcessReplyStates {\n PROCESS_INIT,\n PROCESS_PACKET_LENGTH,\n PROCESS_PACKET_FINISH,\n PROCESS_PACKET\n};\n\n\nenum WS_MessageIds {\n MSGID_NONE = 0,\n\n MSGID_DISCONNECT = 1,\n MSGID_IGNORE = 2,\n MSGID_UNIMPLEMENTED = 3,\n MSGID_DEBUG = 4,\n MSGID_SERVICE_REQUEST = 5,\n MSGID_SERVICE_ACCEPT = 6,\n MSGID_EXT_INFO = 7,\n\n MSGID_KEXINIT = 20,\n MSGID_NEWKEYS = 21,\n\n MSGID_KEXDH_INIT = 30,\n"
|
||||
},
|
||||
{
|
||||
"old": " MSGID_CHANNEL_OPEN_FAIL = 92,\n MSGID_CHANNEL_WINDOW_ADJUST = 93,\n MSGID_CHANNEL_DATA = 94,\n MSGID_CHANNEL_EXTENDED_DATA = 95,\n MSGID_CHANNEL_EOF = 96,\n MSGID_CHANNEL_CLOSE = 97,\n MSGID_CHANNEL_REQUEST = 98,\n MSGID_CHANNEL_SUCCESS = 99,\n MSGID_CHANNEL_FAILURE = 100\n};\n\n\n/* Allows the server to receive up to KEXDH GEX Request during KEX. */\n#define MSGID_KEXDH_LIMIT MSGID_KEXDH_GEX_REQUEST\n\n/* The endpoints should not allow message IDs greater than or\n * equal to msgid 80 before user authentication is complete.\n * Per RFC 4252 section 6. */\n#define MSGID_USERAUTH_LIMIT 80\n\n/* The client should only send the user auth request message\n * (50), it should not accept it. The server should only receive\n * the user auth request message, it should not accept the other\n * user auth messages, it sends them. (>50) */\n#define MSGID_USERAUTH_RESTRICT 50\n\n\n#define CHANNEL_EXTENDED_DATA_STDERR WOLFSSH_EXT_DATA_STDERR\n\n\n/* dynamic memory types */\nenum WS_DynamicTypes {\n DYNTYPE_STRING = 500,\n DYNTYPE_CTX,\n DYNTYPE_SSH,\n DYNTYPE_CHANNEL,\n DYNTYPE_BUFFER,\n DYNTYPE_ID,\n DYNTYPE_HS,\n DYNTYPE_CA,\n DYNTYPE_CERT,\n",
|
||||
"new": " MSGID_CHANNEL_OPEN_FAIL = 92,\n MSGID_CHANNEL_WINDOW_ADJUST = 93,\n MSGID_CHANNEL_DATA = 94,\n MSGID_CHANNEL_EXTENDED_DATA = 95,\n MSGID_CHANNEL_EOF = 96,\n MSGID_CHANNEL_CLOSE = 97,\n MSGID_CHANNEL_REQUEST = 98,\n MSGID_CHANNEL_SUCCESS = 99,\n MSGID_CHANNEL_FAILURE = 100\n};\n\n\n/* The following message ID ranges are described in RFC 5251, section 7. */\nenum WS_MessageIdLimits {\n/* Transport Layer Protocol: */\n MSGIDLIMIT_TRANS_MIN = 1,\n MSGIDLIMIT_TRANS_GEN_MIN = 1,\n MSGIDLIMIT_TRANS_GEN_MAX = 19,\n MSGIDLIMIT_TRANS_ALGO_MIN = 20,\n MSGIDLIMIT_TRANS_ALGO_MAX = 29,\n MSGIDLIMIT_TRANS_KEX_MIN = 30,\n MSGIDLIMIT_TRANS_KEX_MAX = 49,\n MSGIDLIMIT_TRANS_MAX = 49,\n/* User Authentication Protocol: */\n MSGIDLIMIT_AUTH_MIN = 50,\n MSGIDLIMIT_AUTH_GEN_MIN = 50,\n MSGIDLIMIT_AUTH_GEN_MAX = 59,\n MSGIDLIMIT_AUTH_METH_MIN = 60,\n MSGIDLIMIT_AUTH_METH_MAX = 79,\n MSGIDLIMIT_AUTH_MAX = 79,\n/* Connection Protocol: */\n MSGIDLIMIT_CONN_MIN = 80,\n MSGIDLIMIT_CONN_GEN_MIN = 80,\n MSGIDLIMIT_CONN_GEN_MAX = 89,\n MSGIDLIMIT_CONN_CHAN_MIN = 90,\n MSGIDLIMIT_CONN_CHAN_MAX = 127,\n MSGIDLIMIT_CONN_MAX = 127,\n/* Reserved For Client Protocols: */\n MSGIDLIMIT_RESERVED_MIN = 128,\n MSGIDLIMIT_RESERVED_MAX = 191,\n/* Local Extensions: */\n MSGIDLIMIT_EXTENDED_MIN = 192,\n MSGIDLIMIT_EXTENDED_MAX = 255,\n};\n\n/* Message ID bounds checking. */\n#define MSGIDLIMIT_BOUND(x,y,z) ((x) >= (y) && (x) <= (z))\n#define MSGIDLIMIT_COMP(x,name) \\\n MSGIDLIMIT_BOUND((x),MSGIDLIMIT_##name##_MIN,MSGIDLIMIT_##name##_MAX)\n#define MSGIDLIMIT_TRANS(x) MSGIDLIMIT_COMP((x),TRANS)\n#define MSGIDLIMIT_TRANS_GEN(x) MSGIDLIMIT_COMP((x),TRANS_GEN)\n#define MSGIDLIMIT_TRANS_ALGO(x) MSGIDLIMIT_COMP((x),TRANS_ALGO)\n#define MSGIDLIMIT_TRANS_KEX(x) MSGIDLIMIT_COMP((x),TRANS_KEX)\n#define MSGIDLIMIT_AUTH(x) MSGIDLIMIT_COMP((x),AUTH)\n#define MSGIDLIMIT_AUTH_GEN(x) MSGIDLIMIT_COMP((x),AUTH_GEN)\n#define MSGIDLIMIT_AUTH_METH(x) MSGIDLIMIT_COMP((x),AUTH_METH)\n#define MSGIDLIMIT_CONN(x) MSGIDLIMIT_COMP((x),CONN)\n#define MSGIDLIMIT_CONN_GEN(x) MSGIDLIMIT_COMP((x),CONN_GEN)\n#define MSGIDLIMIT_CONN_CHAN(x) MSGIDLIMIT_COMP((x),CONN_CHAN)\n#define MSGIDLIMIT_RESERVED(x) MSGIDLIMIT_COMP((x),RESERVED)\n#define MSGIDLIMIT_EXTENDED(x) MSGIDLIMIT_COMP((x),EXTENDED)\n#define MSGIDLIMIT_POST_USERAUTH(x) ((x) >= MSGIDLIMIT_CONN_MIN)\n\n\n#define CHANNEL_EXTENDED_DATA_STDERR WOLFSSH_EXT_DATA_STDERR\n\n/* Used when checking IsMessageAllowed() to determine if creating and sending\n * the message or receiving the message is allowed */\n#define WS_MSG_SEND 1\n#define WS_MSG_RECV 2\n\n/* dynamic memory types */\nenum WS_DynamicTypes {\n DYNTYPE_STRING = 500,\n DYNTYPE_CTX,\n DYNTYPE_SSH,\n DYNTYPE_CHANNEL,\n DYNTYPE_BUFFER,\n DYNTYPE_ID,\n DYNTYPE_HS,\n DYNTYPE_CA,\n DYNTYPE_CERT,\n"
|
||||
},
|
||||
{
|
||||
"old": "\n\n#define WOLFSSL_V5_0_0 0x05000000\n#define WOLFSSL_V5_7_0 0x05007000\n#define WOLFSSL_V5_7_2 0x05007002\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _WOLFSSH_INTERNAL_H_ */\n\n",
|
||||
"new": "\n\n#define WOLFSSL_V5_0_0 0x05000000\n#define WOLFSSL_V5_7_0 0x05007000\n#define WOLFSSL_V5_7_2 0x05007002\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _WOLFSSH_INTERNAL_H_ */\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"793": {
|
||||
"url": "https://patch-diff.githubusercontent.com/raw/wolfSSL/wolfssh/pull/793.patch",
|
||||
"sha256": "66aa999521800371f97b340db2bff162be4e8ffab4b4b953f9d32b8e33f56cea",
|
||||
"commits": [
|
||||
"5fa6c0fce30a421879b355a007ef843eb48332d3",
|
||||
"af45bc3719ddeac112d9d70b2e6a969f1aa3f3e7",
|
||||
"d74c942c84d44fb46d3a10cb56233b704733e466",
|
||||
"ff95f3c3029d766b114a91d98b013e0a1636a6c1",
|
||||
"2a11471bb717a2ee6f06b3e1beab8a3e2b0ef261",
|
||||
"813ec263cc56e7c9093135d854b3fc887633d368",
|
||||
"cc17941a6125daefbadb8c236fdeaeb1a21ec786",
|
||||
"4862400a374253216e596ff5c3b018b857015cbb"
|
||||
]
|
||||
},
|
||||
"819": {
|
||||
"url": "https://patch-diff.githubusercontent.com/raw/wolfSSL/wolfssh/pull/819.patch",
|
||||
"sha256": "8e63c2b24679a7d831f7dba12e412d2f8a7fdc391fc4e8fd33f029487110219b",
|
||||
"commits": [
|
||||
"201029797b260eee894b12d488bce6022290bf67"
|
||||
]
|
||||
},
|
||||
"840": {
|
||||
"url": "https://patch-diff.githubusercontent.com/raw/wolfSSL/wolfssh/pull/840.patch",
|
||||
"sha256": "23e25873cb4dfa36063357111019e0960dfc008a68cc29d6e2d5c37bde47ec94",
|
||||
"commits": [
|
||||
"9dc1071da7e560db2ea899fa23aab885a25ea862",
|
||||
"024b14124aa2434e90468408b94121c897311f37"
|
||||
]
|
||||
},
|
||||
"855": {
|
||||
"url": "https://patch-diff.githubusercontent.com/raw/wolfSSL/wolfssh/pull/855.patch",
|
||||
"sha256": "b94393df9528f66f6df1aba94015331fee3110c9ea2007a0eff369d8887b4b29",
|
||||
"commits": [
|
||||
"73b165651c80a20047d913d32b0ffac47cb99ef6",
|
||||
"a87ab400b3900d1e7fdda33c898094d6e3ada21d",
|
||||
"5ae5c250e2d9b3bfdaea4f9c73cdf4b9f2592daa",
|
||||
"dee1c59f263220ecd05a88a72da104c22bef0598",
|
||||
"2e5484f36f279484ca06e02ef34ddd420fc0cf87",
|
||||
"03ca9221a36a2a7160a99aeee7bc7ea8368013b5",
|
||||
"2086f34ff37911a1fa388f843ee9d336e740bf44"
|
||||
]
|
||||
},
|
||||
"921": {
|
||||
"url": "https://patch-diff.githubusercontent.com/raw/wolfSSL/wolfssh/pull/921.patch",
|
||||
"sha256": "f6c88598d7f3c94d92c31cecc4ef1e6d779b49f9eff6556ac1c57426d272d504",
|
||||
"commits": [
|
||||
"e9d288ec603531a1d544e77fb1bbdf634cb2a57f"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user