Skip to content

Commit 8efa825

Browse files
authored
Merge pull request #937 from yosuke-wolfssl/f_865
Fix DoUserAuthBanner()
2 parents 8643d7b + fe89681 commit 8efa825

3 files changed

Lines changed: 106 additions & 1 deletion

File tree

src/internal.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8514,7 +8514,7 @@ static int DoUserAuthBanner(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
85148514
ret = GetString(banner, &bannerSz, buf, len, idx);
85158515

85168516
if (ret == WS_SUCCESS)
8517-
ret = GetSize(&bannerSz, buf, len, idx);
8517+
ret = GetSkip(buf, len, idx);
85188518

85198519
if (ret == WS_SUCCESS) {
85208520
if (ssh->ctx->showBanner) {
@@ -10702,6 +10702,12 @@ int wolfSSH_TestDoReceive(WOLFSSH* ssh)
1070210702
{
1070310703
return DoReceive(ssh);
1070410704
}
10705+
10706+
int wolfSSH_TestDoUserAuthBanner(WOLFSSH* ssh, byte* buf, word32 len,
10707+
word32* idx)
10708+
{
10709+
return DoUserAuthBanner(ssh, buf, len, idx);
10710+
}
1070510711
#endif
1070610712

1070710713

tests/unit.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,97 @@ static int test_DhGexGroupValidate(void)
626626
#endif /* WOLFSSH_TEST_INTERNAL && !WOLFSSH_NO_DH_GEX_SHA256 */
627627

628628

629+
#ifdef WOLFSSH_TEST_INTERNAL
630+
631+
/* Verify DoUserAuthBanner fully consumes the payload, including a non-empty
632+
* language tag. Before the fix, the tag's data bytes were left unconsumed,
633+
* which would misalign packet decoding for subsequent messages. */
634+
static int test_DoUserAuthBanner(void)
635+
{
636+
WOLFSSH_CTX* ctx = NULL;
637+
WOLFSSH* ssh = NULL;
638+
int result = 0;
639+
640+
/* Payload layout: [4-byte banner len][banner][4-byte lang len][lang] */
641+
struct {
642+
const char* banner;
643+
word32 bannerSz;
644+
const char* lang;
645+
word32 langSz;
646+
int expectRet;
647+
const char* label;
648+
} cases[] = {
649+
{ "Welcome", 7, "", 0, WS_SUCCESS, "empty lang tag" },
650+
{ "Welcome", 7, "en-US", 5, WS_SUCCESS, "non-empty lang tag" },
651+
{ NULL, 0, NULL, 0, WS_BAD_ARGUMENT, "null ssh" },
652+
};
653+
int i;
654+
655+
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
656+
if (ctx == NULL)
657+
return -300;
658+
ssh = wolfSSH_new(ctx);
659+
if (ssh == NULL) {
660+
wolfSSH_CTX_free(ctx);
661+
return -301;
662+
}
663+
ctx->showBanner = 0;
664+
665+
for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) {
666+
byte buf[128];
667+
word32 idx = 0;
668+
word32 len = 0;
669+
int ret;
670+
671+
if (cases[i].banner == NULL) {
672+
/* null-ssh case: pass NULL ssh, dummy non-null buf */
673+
buf[0] = 0;
674+
len = 1;
675+
ret = wolfSSH_TestDoUserAuthBanner(NULL, buf, len, &idx);
676+
}
677+
else {
678+
/* encode banner string */
679+
buf[len++] = (byte)(cases[i].bannerSz >> 24);
680+
buf[len++] = (byte)(cases[i].bannerSz >> 16);
681+
buf[len++] = (byte)(cases[i].bannerSz >> 8);
682+
buf[len++] = (byte)(cases[i].bannerSz);
683+
WMEMCPY(buf + len, cases[i].banner, cases[i].bannerSz);
684+
len += cases[i].bannerSz;
685+
/* encode language tag string */
686+
buf[len++] = (byte)(cases[i].langSz >> 24);
687+
buf[len++] = (byte)(cases[i].langSz >> 16);
688+
buf[len++] = (byte)(cases[i].langSz >> 8);
689+
buf[len++] = (byte)(cases[i].langSz);
690+
WMEMCPY(buf + len, cases[i].lang, cases[i].langSz);
691+
len += cases[i].langSz;
692+
693+
ret = wolfSSH_TestDoUserAuthBanner(ssh, buf, len, &idx);
694+
}
695+
696+
if (ret != cases[i].expectRet) {
697+
printf("DoUserAuthBanner[%s]: ret=%d, expected=%d\n",
698+
cases[i].label, ret, cases[i].expectRet);
699+
result = -302 - i;
700+
break;
701+
}
702+
703+
/* On success the entire payload must be consumed. */
704+
if (ret == WS_SUCCESS && idx != len) {
705+
printf("DoUserAuthBanner[%s]: idx=%u, len=%u (unconsumed bytes)\n",
706+
cases[i].label, idx, len);
707+
result = -310 - i;
708+
break;
709+
}
710+
}
711+
712+
wolfSSH_free(ssh);
713+
wolfSSH_CTX_free(ctx);
714+
return result;
715+
}
716+
717+
#endif /* WOLFSSH_TEST_INTERNAL */
718+
719+
629720
/* Error Code And Message Test */
630721

631722
static int test_Errors(void)
@@ -714,6 +805,12 @@ int wolfSSH_UnitTest(int argc, char** argv)
714805
testResult = testResult || unitResult;
715806
#endif
716807

808+
#ifdef WOLFSSH_TEST_INTERNAL
809+
unitResult = test_DoUserAuthBanner();
810+
printf("DoUserAuthBanner: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED"));
811+
testResult = testResult || unitResult;
812+
#endif
813+
717814
#ifdef WOLFSSH_KEYGEN
718815
#ifndef WOLFSSH_NO_RSA
719816
unitResult = test_RsaKeyGen();

wolfssh/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,8 @@ enum WS_MessageIdLimits {
13271327
WOLFSSH_API int wolfSSH_TestIsMessageAllowed(WOLFSSH* ssh, byte msg,
13281328
byte state);
13291329
WOLFSSH_API int wolfSSH_TestDoReceive(WOLFSSH* ssh);
1330+
WOLFSSH_API int wolfSSH_TestDoUserAuthBanner(WOLFSSH* ssh, byte* buf,
1331+
word32 len, word32* idx);
13301332
#ifndef WOLFSSH_NO_DH_GEX_SHA256
13311333
WOLFSSH_API int wolfSSH_TestValidateKexDhGexGroup(const byte* primeGroup,
13321334
word32 primeGroupSz, const byte* generator, word32 generatorSz,

0 commit comments

Comments
 (0)