Skip to content

Commit 7853fc6

Browse files
committed
fix: always send USERAUTH_FAILURE on reject
RFC 4252 section 5.1 has the server answer a request it does not accept with USERAUTH_FAILURE. A callback returning WOLFSSH_USERAUTH_REJECTED now always gets that reply. NO_FAILURE_ON_REJECTED suppressed it. The macro was never set by configure, named in a header, or documented, and it guarded all four method handlers alike. - drop the macro and its four guards - add test_UserAuthRejectedSendsFailure(), asserting on the wire, since the handler returns WS_USER_AUTH_E either way Issue: F-11672
1 parent 9731cfe commit 7853fc6

2 files changed

Lines changed: 77 additions & 11 deletions

File tree

src/internal.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8506,11 +8506,9 @@ static int DoUserAuthRequestNone(WOLFSSH* ssh, WS_UserAuthData* authData,
85068506
}
85078507
else if (ret == WOLFSSH_USERAUTH_REJECTED) {
85088508
WLOG(WS_LOG_DEBUG, "DUARN: none rejected");
8509-
#ifndef NO_FAILURE_ON_REJECTED
85108509
/* Count before failing: a send that blocks returns
85118510
* WS_WANT_WRITE, which isn't fatal on its own. */
85128511
(void)SendUserAuthFailureCount(ssh, 0, countIt);
8513-
#endif
85148512
ret = WS_USER_AUTH_E;
85158513
}
85168514
else if (ret == WOLFSSH_USERAUTH_WOULD_BLOCK) {
@@ -8639,9 +8637,7 @@ static int DoUserAuthInfoResponse(WOLFSSH* ssh,
86398637
}
86408638
else if (ret == WOLFSSH_USERAUTH_REJECTED) {
86418639
WLOG(WS_LOG_DEBUG, "DUARKB: keyboard rejected");
8642-
#ifndef NO_FAILURE_ON_REJECTED
8643-
authFailure = 1;
8644-
#endif
8640+
authFailure = 1;
86458641
authRejected = 1;
86468642
ret = WS_USER_AUTH_E;
86478643
}
@@ -8754,9 +8750,7 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData,
87548750
}
87558751
else if (ret == WOLFSSH_USERAUTH_REJECTED) {
87568752
WLOG(WS_LOG_DEBUG, "DUARPW: password rejected");
8757-
#ifndef NO_FAILURE_ON_REJECTED
8758-
authFailure = 1;
8759-
#endif
8753+
authFailure = 1;
87608754
authRejected = 1;
87618755
ret = WS_USER_AUTH_E;
87628756
}
@@ -10186,9 +10180,7 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
1018610180
ret = WS_AUTH_PENDING;
1018710181
}
1018810182
else if (ret == WOLFSSH_USERAUTH_REJECTED) {
10189-
#ifndef NO_FAILURE_ON_REJECTED
10190-
authFailure = 1;
10191-
#endif
10183+
authFailure = 1;
1019210184
authRejected = 1;
1019310185
ret = WS_USER_AUTH_E;
1019410186
}

tests/unit.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7959,6 +7959,75 @@ static int CaptureIoSendAuthSvc(WOLFSSH* ssh, void* buf, word32 sz, void* ctx)
79597959
return (int)sz;
79607960
}
79617961

7962+
/* Userauth callback that rejects outright. */
7963+
static int UnitAuthAlwaysReject(byte authType, WS_UserAuthData* authData,
7964+
void* ctx)
7965+
{
7966+
(void)authType;
7967+
(void)authData;
7968+
(void)ctx;
7969+
return WOLFSSH_USERAUTH_REJECTED;
7970+
}
7971+
7972+
7973+
/* RFC 4252 section 5.1: a rejected request is answered with
7974+
* USERAUTH_FAILURE. The handler returns WS_USER_AUTH_E either way, so the
7975+
* assertion is on what went out on the wire. */
7976+
static int test_UserAuthRejectedSendsFailure(void)
7977+
{
7978+
WOLFSSH_CTX* ctx = NULL;
7979+
WOLFSSH* ssh = NULL;
7980+
byte request[128];
7981+
word32 requestSz;
7982+
word32 idx = 0;
7983+
int ret;
7984+
int result = 0;
7985+
7986+
requestSz = BuildAuthPwRequest(request, (word32)sizeof(request));
7987+
if (requestSz == 0)
7988+
return -790;
7989+
7990+
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
7991+
if (ctx == NULL)
7992+
return -791;
7993+
wolfSSH_SetUserAuth(ctx, UnitAuthAlwaysReject);
7994+
wolfSSH_SetIOSend(ctx, CaptureIoSendAuthSvc);
7995+
7996+
ssh = wolfSSH_new(ctx);
7997+
if (ssh == NULL) {
7998+
wolfSSH_CTX_free(ctx);
7999+
return -792;
8000+
}
8001+
8002+
s_authSvcCaptureSz = 0;
8003+
s_authSvcSendCount = 0;
8004+
8005+
ret = wolfSSH_TestDoUserAuthRequest(ssh, request, requestSz, &idx);
8006+
8007+
if (ret != WS_USER_AUTH_E) {
8008+
printf("UserAuthRejectedSendsFailure: ret=%d expected %d\n",
8009+
ret, WS_USER_AUTH_E);
8010+
result = -793;
8011+
}
8012+
else if (s_authSvcSendCount == 0) {
8013+
printf("UserAuthRejectedSendsFailure: nothing sent on rejection\n");
8014+
result = -794;
8015+
}
8016+
else if (CaptureMsgId(s_authSvcCapture, s_authSvcCaptureSz)
8017+
!= MSGID_USERAUTH_FAILURE) {
8018+
printf("UserAuthRejectedSendsFailure: msgId=%d expected"
8019+
" USERAUTH_FAILURE\n",
8020+
CaptureMsgId(s_authSvcCapture, s_authSvcCaptureSz));
8021+
result = -795;
8022+
}
8023+
8024+
wolfSSH_free(ssh);
8025+
wolfSSH_CTX_free(ctx);
8026+
8027+
return result;
8028+
}
8029+
8030+
79628031
/* Verify DoUserAuthRequest rejects non-"ssh-connection" service names per
79638032
* RFC 4252 Section 5. For each case we assert:
79648033
* 1. ret == WS_SUCCESS (connection stays open for retry)
@@ -17715,6 +17784,11 @@ int wolfSSH_UnitTest(int argc, char** argv)
1771517784
(unitResult == 0 ? "SUCCESS" : "FAILED"));
1771617785
testResult = testResult || unitResult;
1771717786

17787+
unitResult = test_UserAuthRejectedSendsFailure();
17788+
printf("UserAuthRejectedSendsFailure: %s\n",
17789+
(unitResult == 0 ? "SUCCESS" : "FAILED"));
17790+
testResult = testResult || unitResult;
17791+
1771817792
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && \
1771917793
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384)
1772017794
unitResult = test_EccUserAuthCurveMismatch();

0 commit comments

Comments
 (0)