Merge pull request #800 from LinuxJedi/kbi-fixes

Make Keyboard Interactive a compile time option
pull/801/head
John Safranek 2025-05-05 14:02:16 -07:00 committed by GitHub
commit 24b7629d78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 299 additions and 22 deletions

View File

@ -72,6 +72,7 @@ jobs:
'--enable-all',
'--enable-sftp',
'--enable-scp',
'--enable-keyboard-interactive',
'--enable-shell',
]
name: Build wolfssh

View File

@ -126,6 +126,11 @@ AC_ARG_ENABLE([keygen],
[AS_HELP_STRING([--enable-keygen],[Enable key generation (default: disabled)])],
[ENABLED_KEYGEN=$enableval],[ENABLED_KEYGEN=no])
# Keyboard Interactive
AC_ARG_ENABLE([keyboard-interactive],
[AS_HELP_STRING([--enable-keyboard-interactive],[Enable keyboard interactive authentication (default: disabled)])],
[ENABLED_KEYBOARD_INTERACTIVE=$enableval],[ENABLED_KEYBOARD_INTERACTIVE=no])
# SCP
AC_ARG_ENABLE([scp],
[AS_HELP_STRING([--enable-scp],[Enable scp support (default: disabled)])],
@ -206,7 +211,7 @@ AC_ARG_ENABLE([distro],
AS_IF([test "x$ENABLED_DISTRO" = "xyes"],
[ENABLED_ALL=yes; enable_shared=yes; enable_static=yes])
AS_IF([test "x$ENABLED_ALL" = "xyes"],
[ENABLED_KEYGEN=yes; ENABLED_SCP=yes; ENABLED_SFTP=yes; ENABLED_FWD=yes; ENABLED_SHELL=yes; ENABLED_AGENT=yes; ENABLED_SSHD=yes; ENABLED_SSHCLIENT=yes; ENABLED_CERTS=yes])
[ENABLED_KEYGEN=yes; ENABLED_SCP=yes; ENABLED_SFTP=yes; ENABLED_FWD=yes; ENABLED_SHELL=yes; ENABLED_AGENT=yes; ENABLED_SSHD=yes; ENABLED_SSHCLIENT=yes; ENABLED_CERTS=yes; ENABLED_KEYBOARD_INTERACTIVE=yes])
AS_IF([test "x$ENABLED_SSHD" = "xyes"],
[ENABLED_SHELL=yes])
@ -215,6 +220,8 @@ AS_IF([test "x$ENABLED_INLINE" = "xno"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DNO_INLINE"])
AS_IF([test "x$ENABLED_KEYGEN" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_KEYGEN"])
AS_IF([test "x$ENABLED_KEYBOARD_INTERACTIVE" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_KEYBOARD_INTERACTIVE"])
AS_IF([test "x$ENABLED_SCP" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SCP"])
AS_IF([test "x$ENABLED_SFTP" = "xyes"],
@ -292,6 +299,7 @@ AM_CONDITIONAL([BUILD_SSHD],[test "x$ENABLED_SSHD" = "xyes"])
AM_CONDITIONAL([BUILD_SSHCLIENT],[test "x$ENABLED_SSHCLIENT" = "xyes"])
AM_CONDITIONAL([BUILD_CERTS],[test "x$ENABLED_CERTS" = "xyes"])
AM_CONDITIONAL([BUILD_TPM],[test "x$ENABLED_TPM" = "xyes"])
AM_CONDITIONAL([BUILD_KEYBOARD_INTERACTIVE],[test "x$ENABLED_KEYBOARD_INTERACTIVE" = "xyes"])
AX_HARDEN_CC_COMPILER_FLAGS
@ -328,6 +336,7 @@ AS_ECHO([" Features"])
AS_ECHO([" * Inline Code: $ENABLED_INLINE"])
AS_ECHO([" * Small stack: $ENABLED_SMALLSTACK"])
AS_ECHO([" * keygen: $ENABLED_KEYGEN"])
AS_ECHO([" * keyboard interactive: $ENABLED_KEYBOARD_INTERACTIVE"])
AS_ECHO([" * psuedo-terminal: $ENABLED_TERM"])
AS_ECHO([" * echoserver shell support: $ENABLED_SHELL"])
AS_ECHO([" * scp: $ENABLED_SCP"])

View File

@ -64,10 +64,11 @@ static word32 userPrivateKeySz = 0;
static word32 userPrivateKeyTypeSz = 0;
static byte isPrivate = 0;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static word32 keyboardResponseCount = 0;
static byte** keyboardResponses;
static word32* keyboardResponseLengths;
#endif
#ifdef WOLFSSH_CERTS
#if 0
@ -460,7 +461,7 @@ int ClientUserAuth(byte authType,
{
const char* defaultPassword = (const char*)ctx;
word32 passwordSz = 0;
#ifdef WOLFSSH_TERM
#if defined(WOLFSSH_TERM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
word32 entry;
#endif
int ret = WOLFSSH_USERAUTH_SUCCESS;
@ -474,9 +475,11 @@ int ClientUserAuth(byte authType,
if (authData->type & WOLFSSH_USERAUTH_PUBLICKEY) {
printf(" - publickey\n");
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (authData->type & WOLFSSH_USERAUTH_KEYBOARD) {
printf(" - keyboard\n");
}
#endif
printf("wolfSSH requesting to use type %d\n", authType);
#endif
@ -544,7 +547,7 @@ int ClientUserAuth(byte authType,
authData->sf.password.passwordSz = passwordSz;
}
}
#ifdef WOLFSSH_TERM
#if defined(WOLFSSH_TERM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
else if (authType == WOLFSSH_USERAUTH_KEYBOARD) {
if (authData->sf.keyboard.promptName &&
authData->sf.keyboard.promptName[0] != '\0') {
@ -1112,7 +1115,9 @@ int ClientLoadCA(WOLFSSH_CTX* ctx, const char* caCert)
void ClientFreeBuffers(const char* pubKeyName, const char* privKeyName,
void* heap)
{
#if defined(WOLFSSH_TERM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
word32 entry;
#endif
#ifdef WOLFSSH_TPM
wolfSSH_TPM_Cleanup(&tpmDev, &tpmKey);
#endif
@ -1126,9 +1131,11 @@ void ClientFreeBuffers(const char* pubKeyName, const char* privKeyName,
WFREE(userPrivateKey, heap, DYNTYPE_PRIVKEY);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
for (entry = 0; entry < keyboardResponseCount; entry++) {
WFREE(keyboardResponses[entry], NULL, 0);
}
WFREE(keyboardResponses, NULL, 0);
WFREE(keyboardResponseLengths, NULL, 0);
#endif
}

View File

@ -2006,7 +2006,7 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList)
return count;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static int LoadKeyboardList(StrList* strList, PwMapList* mapList)
{
char names[256];
@ -2034,6 +2034,7 @@ static int LoadKeyboardList(StrList* strList, PwMapList* mapList)
return count;
}
#endif
#ifndef NO_FILESYSTEM
static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList)
@ -2183,8 +2184,10 @@ static int wsUserAuth(byte authType,
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
authType != WOLFSSH_USERAUTH_NONE &&
#endif
authType != WOLFSSH_USERAUTH_PUBLICKEY &&
authType != WOLFSSH_USERAUTH_KEYBOARD) {
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
authType != WOLFSSH_USERAUTH_KEYBOARD &&
#endif
authType != WOLFSSH_USERAUTH_PUBLICKEY) {
return WOLFSSH_USERAUTH_FAILURE;
}
@ -2194,6 +2197,7 @@ static int wsUserAuth(byte authType,
authData->sf.password.passwordSz,
authHash);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
else if (authType == WOLFSSH_USERAUTH_KEYBOARD) {
if (authData->sf.keyboard.responseCount != 1) {
return WOLFSSH_USERAUTH_FAILURE;
@ -2202,6 +2206,7 @@ static int wsUserAuth(byte authType,
authData->sf.keyboard.responseLengths[0],
authHash);
}
#endif
else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) {
wc_Sha256Hash(authData->sf.publicKey.publicKey,
authData->sf.publicKey.publicKeySz,
@ -2302,6 +2307,7 @@ static int wsUserAuth(byte authType,
WOLFSSH_USERAUTH_REJECTED;
}
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
else if (authData->type == WOLFSSH_USERAUTH_KEYBOARD) {
if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
@ -2310,6 +2316,7 @@ static int wsUserAuth(byte authType,
return WOLFSSH_USERAUTH_INVALID_PASSWORD;
}
}
#endif
#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
else if (authData->type == WOLFSSH_USERAUTH_NONE) {
return WOLFSSH_USERAUTH_SUCCESS;
@ -2325,6 +2332,7 @@ static int wsUserAuth(byte authType,
return WOLFSSH_USERAUTH_INVALID_USER;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static int keyboardCallback(WS_UserAuthData_Keyboard *kbAuth, void *ctx)
{
WS_UserAuthData_Keyboard *kbAuthData = (WS_UserAuthData_Keyboard*) ctx;
@ -2332,6 +2340,7 @@ static int keyboardCallback(WS_UserAuthData_Keyboard *kbAuth, void *ctx)
return WS_SUCCESS;
}
#endif
#ifdef WOLFSSH_SFTP
/*
@ -2417,9 +2426,11 @@ static void ShowUsage(void)
" load in an X.509 DER cert to accept from peer\n");
printf(" -P <name>:<password>\n"
" add password to accept from peer\n");
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
printf(" -i <name>:<password>\n"
" add passowrd to accept via keyboard-interactive "
"from peer\n");
#endif
#ifdef WOLFSSH_CERTS
printf(" -a <file> load in a root CA certificate file\n");
#endif
@ -2463,8 +2474,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
StrList* derPubKeyList = NULL;
#endif
StrList* passwdList = NULL;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
StrList* keyboardList = NULL;
WS_UserAuthData_Keyboard kbAuthData;
#endif
WS_SOCKET_T listenFd = WOLFSSH_SOCKET_INVALID;
word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK;
word32 threadCount = 0;
@ -2495,7 +2508,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
int argc = serverArgs->argc;
char** argv = serverArgs->argv;
serverArgs->return_code = EXIT_SUCCESS;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
kbAuthData.promptCount = 0;
#endif
if (argc > 0) {
const char* optlist = "?1a:d:efEp:R:Ni:j:i:I:J:K:P:k:b:x:m:c:s:";
@ -2582,9 +2597,11 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
passwdList = StrListAdd(passwdList, myoptarg);
break;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
case 'i':
keyboardList = StrListAdd(keyboardList, myoptarg);
break;
#endif
case 'b':
userAuthWouldBlock = atoi(myoptarg);
@ -2739,6 +2756,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
passwdList = NULL;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (keyboardList) {
LoadKeyboardList(keyboardList, &pwMapList);
StrListFree(keyboardList);
@ -2767,6 +2785,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
kbAuthData.promptEcho[0] = 0;
wolfSSH_SetKeyboardAuthPrompts(ctx, keyboardCallback);
}
#endif
{
const char* bufName = NULL;
@ -2973,7 +2992,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
#endif
wolfSSH_SetUserAuthCtx(ssh, &pwMapList);
wolfSSH_SetKeyingCompletionCbCtx(ssh, (void*)ssh);
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
wolfSSH_SetKeyboardAuthCtx(ssh, &kbAuthData);
#endif
/* Use the session object for its own highwater callback ctx */
if (defaultHighwater > 0) {
wolfSSH_SetHighwaterCtx(ssh, (void*)ssh);
@ -3046,11 +3067,13 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
if (listenFd != WOLFSSH_SOCKET_INVALID) {
WCLOSESOCKET(listenFd);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (kbAuthData.promptCount > 0) {
WFREE(kbAuthData.promptLengths, NULL, 0);
WFREE(kbAuthData.prompts, NULL, 0);
WFREE(kbAuthData.promptEcho, NULL, 0);
}
#endif
wc_FreeMutex(&doneLock);
PwMapListDelete(&pwMapList);
wolfSSH_CTX_free(ctx);

View File

@ -1055,8 +1055,12 @@ WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
ssh->authId = ID_USERAUTH_PUBLICKEY;
ssh->supportedAuth[0] = ID_USERAUTH_PUBLICKEY;
ssh->supportedAuth[1] = ID_USERAUTH_PASSWORD;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
ssh->supportedAuth[2] = ID_USERAUTH_KEYBOARD;
ssh->supportedAuth[3] = ID_NONE; /* ID_NONE is treated as empty slot */
#else
ssh->supportedAuth[2] = ID_NONE; /* ID_NONE is treated as empty slot */
#endif
ssh->nextChannel = DEFAULT_NEXT_CHANNEL;
ssh->blockSz = MIN_BLOCK_SZ;
ssh->encryptId = ID_NONE;
@ -2625,7 +2629,9 @@ static const NameIdPair NameIdMap[] = {
/* UserAuth IDs */
{ ID_USERAUTH_PASSWORD, TYPE_OTHER, "password" },
{ ID_USERAUTH_PUBLICKEY, TYPE_OTHER, "publickey" },
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
{ ID_USERAUTH_KEYBOARD, TYPE_OTHER, "keyboard-interactive" },
#endif
/* Channel Type IDs */
{ ID_CHANTYPE_SESSION, TYPE_OTHER, "session" },
@ -6398,7 +6404,7 @@ static int DoUserAuthRequestNone(WOLFSSH* ssh, WS_UserAuthData* authData,
#endif
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static int DoUserAuthInfoResponse(WOLFSSH* ssh,
byte* buf, word32 len, word32* idx)
{
@ -6541,7 +6547,7 @@ static int DoUserAuthInfoResponse(WOLFSSH* ssh,
return ret;
}
#endif
/* Utility for DoUserAuthRequest() */
static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData,
@ -7781,9 +7787,11 @@ static int DoUserAuthRequest(WOLFSSH* ssh,
if (authNameId == ID_USERAUTH_PASSWORD)
ret = DoUserAuthRequestPassword(ssh, &authData, buf, len, &begin);
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
else if (authNameId == ID_USERAUTH_KEYBOARD) {
ret = SendUserAuthKeyboardRequest(ssh, &authData);
}
#endif
#if !defined(WOLFSSH_NO_RSA) || !defined(WOLFSSH_NO_ECDSA)
else if (authNameId == ID_USERAUTH_PUBLICKEY) {
authData.sf.publicKey.dataToSign = buf + *idx;
@ -7817,9 +7825,14 @@ static int DoUserAuthRequest(WOLFSSH* ssh,
static int DoUserAuthFailure(WOLFSSH* ssh,
byte* buf, word32 len, word32* idx)
{
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
byte authList[4]; /* Should only ever be password, publickey, hostname,
keyboard */
word32 authListSz = 4;
#else
byte authList[3];
word32 authListSz = 3;
#endif
byte partialSuccess;
byte authType = 0;
int ret = WS_SUCCESS;
@ -7852,9 +7865,11 @@ static int DoUserAuthFailure(WOLFSSH* ssh,
case ID_USERAUTH_PASSWORD:
authType |= WOLFSSH_USERAUTH_PASSWORD;
break;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
case ID_USERAUTH_KEYBOARD:
authType |= WOLFSSH_USERAUTH_KEYBOARD;
break;
#endif
#if !defined(WOLFSSH_NO_RSA) || !defined(WOLFSSH_NO_ECDSA)
case ID_USERAUTH_PUBLICKEY:
authType |= WOLFSSH_USERAUTH_PUBLICKEY;
@ -7898,9 +7913,11 @@ static int DoUserAuthSuccess(WOLFSSH* ssh,
return ret;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (ssh->serverState == SERVER_USERAUTH_ACCEPT_KEYBOARD)
ssh->serverState = SERVER_USERAUTH_ACCEPT_KEYBOARD_DONE;
else
#endif
ssh->serverState = SERVER_USERAUTH_ACCEPT_DONE;
WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthSuccess(), ret = %d", ret);
@ -7935,7 +7952,7 @@ static int DoUserAuthBanner(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
return ret;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static int DoUserAuthInfoRequest(WOLFSSH* ssh, byte* buf, word32 len,
word32* idx)
{
@ -8036,7 +8053,7 @@ static int DoUserAuthInfoRequest(WOLFSSH* ssh, byte* buf, word32 len,
return ret;
}
#endif
#ifdef WOLFSSH_FWD
static int DoGlobalRequestFwd(WOLFSSH* ssh,
@ -9388,6 +9405,7 @@ static int DoPacket(WOLFSSH* ssh, byte* bufferConsumed)
ret = DoUserAuthRequest(ssh, buf + idx, payloadSz, &payloadIdx);
break;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
case MSGID_USERAUTH_INFO_RESPONSE:
WLOG(WS_LOG_DEBUG, "Decoding MSG_USERAUTH_INFO_RESPONSE");
ret = DoUserAuthInfoResponse(ssh, buf + idx, payloadSz, &payloadIdx);
@ -9397,6 +9415,7 @@ static int DoPacket(WOLFSSH* ssh, byte* bufferConsumed)
WLOG(WS_LOG_DEBUG, "Decoding MSGID_USERAUTH_INFO_REQUEST");
ret = DoUserAuthInfoRequest(ssh, buf + idx, payloadSz, &payloadIdx);
break;
#endif
case MSGID_USERAUTH_FAILURE:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_USERAUTH_FAILURE");
@ -13225,6 +13244,7 @@ static int BuildUserAuthRequestPassword(WOLFSSH* ssh,
return ret;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static int PrepareUserAuthRequestKeyboard(WOLFSSH* ssh, word32* payloadSz,
const WS_UserAuthData* authData)
{
@ -13444,6 +13464,7 @@ static int BuildUserAuthResponseKeyboard(WOLFSSH* ssh, byte* output, word32* idx
return ret;
}
#endif
#ifndef WOLFSSH_NO_RSA
static int PrepareUserAuthRequestRsa(WOLFSSH* ssh, word32* payloadSz,
@ -14775,6 +14796,7 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh,
#endif /* !WOLFSSH_NO_RSA || !WOLFSSH_NO_ECDSA || !WOLFSSH_NO_ED25519 */
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
int SendUserAuthKeyboardResponse(WOLFSSH* ssh)
{
byte* output;
@ -14864,6 +14886,7 @@ int SendUserAuthKeyboardResponse(WOLFSSH* ssh)
return ret;
}
#endif
int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
{
@ -14897,11 +14920,14 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
WMEMSET(keySig_ptr, 0, sizeof(WS_KeySignature));
keySig_ptr->keySigId = ID_NONE;
keySig_ptr->heap = ssh->ctx->heap;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
/* Callback happens later for keyboard auth */
if (authType & WOLFSSH_USERAUTH_KEYBOARD) {
authId = ID_USERAUTH_KEYBOARD;
}
else if (ssh->ctx->userAuthCb != NULL) {
else
#endif
if (ssh->ctx->userAuthCb != NULL) {
WLOG(WS_LOG_DEBUG, "SUAR: Calling the userauth callback");
WMEMSET(&authData, 0, sizeof(authData));
@ -14927,8 +14953,13 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
/* fall into public key case if keyboard or password case was not
* successful */
if ((ret == WS_FATAL_ERROR ||
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
(!(authType & WOLFSSH_USERAUTH_PASSWORD) &&
!(authType & WOLFSSH_USERAUTH_KEYBOARD))) &&
#else
!(authType & WOLFSSH_USERAUTH_PASSWORD)) &&
#endif
(authType & WOLFSSH_USERAUTH_PUBLICKEY)) {
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY,
&authData, ssh->userAuthCtx);
@ -14966,7 +14997,10 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
ret = PrepareUserAuthRequestPublicKey(ssh, &payloadSz, &authData,
keySig_ptr);
}
else if (authId != ID_NONE && authId != ID_USERAUTH_KEYBOARD &&
else if (authId != ID_NONE &&
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
authId != ID_USERAUTH_KEYBOARD &&
#endif
!ssh->userAuthPkDone)
ret = WS_INVALID_ALGO_ID;
}
@ -15006,6 +15040,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
ret = BuildUserAuthRequestPassword(ssh, output, &idx, &authData);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
else if (authId == ID_USERAUTH_KEYBOARD) {
/* language tag, deprecated, should be empty */
c32toa(0, output + idx);
@ -15014,6 +15049,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
c32toa(0, output + idx);
idx += LENGTH_SZ;
}
#endif
else if (authId == ID_USERAUTH_PUBLICKEY)
ret = BuildUserAuthRequestPublicKey(ssh, output, &idx, &authData,
sigStart, sigStartIdx, keySig_ptr);
@ -15054,9 +15090,11 @@ static int GetAllowedAuth(WOLFSSH* ssh, char* authStr)
return WS_BAD_ARGUMENT;
typeAllowed |= WOLFSSH_USERAUTH_PASSWORD;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (ssh->ctx->keyboardAuthCb != NULL) {
typeAllowed |= WOLFSSH_USERAUTH_KEYBOARD;
}
#endif
#if !defined(WOLFSSH_NO_RSA) || !defined(WOLFSSH_NO_ECDSA)
typeAllowed |= WOLFSSH_USERAUTH_PUBLICKEY;
#endif
@ -15073,9 +15111,11 @@ static int GetAllowedAuth(WOLFSSH* ssh, char* authStr)
WSTRNCAT(authStr, "password,", MAX_AUTH_STRING-1);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (typeAllowed & WOLFSSH_USERAUTH_KEYBOARD) {
WSTRNCAT(authStr, "keyboard-interactive,", MAX_AUTH_STRING-1);
}
#endif
/* remove last comma from the list */
return (int)XSTRLEN(authStr) - 1;

View File

@ -891,6 +891,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
}
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
while (ssh->serverState == SERVER_USERAUTH_ACCEPT_KEYBOARD) {
if ( (ssh->error = SendUserAuthKeyboardResponse(ssh)) <
WS_SUCCESS) {
@ -911,6 +912,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
}
}
}
#endif
ssh->connectState = CONNECT_SERVER_USERAUTH_ACCEPT_DONE;
WLOG(WS_LOG_DEBUG, connectState, "SERVER_USERAUTH_ACCEPT_DONE");
@ -1360,6 +1362,7 @@ int wolfSSH_SendDisconnect(WOLFSSH *ssh, word32 reason)
return SendDisconnect(ssh, reason);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
void wolfSSH_SetKeyboardAuthPrompts(WOLFSSH_CTX* ctx,
WS_CallbackKeyboardAuthPrompts cb)
{
@ -1374,6 +1377,7 @@ void wolfSSH_SetKeyboardAuthCtx(WOLFSSH* ssh, void* keyboardAuthCtx)
ssh->keyboardAuthCtx = keyboardAuthCtx;
}
}
#endif
void wolfSSH_SetUserAuth(WOLFSSH_CTX* ctx, WS_CallbackUserAuth cb)
{

View File

@ -1555,6 +1555,7 @@ static void test_wolfSSH_QueryAlgoList(void)
AssertIntEQ(WS_INVALID_ALGO_ID, k);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
#if defined(WOLFSSH_SFTP) && !defined(NO_WOLFSSH_CLIENT) && \
!defined(SINGLE_THREADED)
@ -1699,6 +1700,7 @@ static void test_wolfSSH_KeyboardInteractive(void)
#else /* WOLFSSH_SFTP && !NO_WOLFSSH_CLIENT && !SINGLE_THREADED */
static void test_wolfSSH_KeyboardInteractive(void) { ; }
#endif /* WOLFSSH_SFTP && !NO_WOLFSSH_CLIENT && !SINGLE_THREADED */
#endif /* WOLFSSH_KEYBOARD_INTERACTIVE */
#endif /* WOLFSSH_TEST_BLOCK */
@ -1735,7 +1737,9 @@ int wolfSSH_ApiTest(int argc, char** argv)
test_wolfSSH_ReadKey();
test_wolfSSH_QueryAlgoList();
test_wolfSSH_SetAlgoList();
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
test_wolfSSH_KeyboardInteractive();
#endif
/* SCP tests */
test_wolfSSH_SCP_CB();

View File

@ -145,7 +145,7 @@
#if !defined(NO_WOLFSSH_SERVER) && !defined(NO_WOLFSSH_CLIENT) && \
!defined(SINGLE_THREADED) && !defined(WOLFSSH_TEST_BLOCK) && \
!defined(NO_FILESYSTEM)
!defined(NO_FILESYSTEM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
const char *testText1 = "test";
const char *testText2 = "password";
@ -387,7 +387,6 @@ static THREAD_RETURN WOLFSSH_THREAD server_thread(void* args)
WOLFSSL_RETURN_FROM_THREAD(0);
}
static int keyboardUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
{
(void) ctx;
@ -575,7 +574,6 @@ static void test_unbalanced_client_KeyboardInteractive(void)
test_client();
unbalanced = 0;
}
#endif /* WOLFSSH_TEST_BLOCK */
int wolfSSH_AuthTest(int argc, char** argv)
@ -585,7 +583,7 @@ int wolfSSH_AuthTest(int argc, char** argv)
#if defined(NO_WOLFSSH_SERVER) || defined(NO_WOLFSSH_CLIENT) || \
defined(SINGLE_THREADED) || defined(WOLFSSH_TEST_BLOCK) || \
defined(NO_FILESYSTEM)
defined(NO_FILESYSTEM) || !defined(WOLFSSH_KEYBOARD_INTERACTIVE)
return 77;
#else
AssertIntEQ(wolfSSH_Init(), WS_SUCCESS);

View File

@ -3,7 +3,7 @@
# All paths should be given relative to the root
check_PROGRAMS += tests/unit.test tests/api.test \
tests/testsuite.test tests/auth.test tests/kex.test
tests/testsuite.test tests/kex.test
tests_unit_test_SOURCES = tests/unit.c tests/unit.h
tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER
@ -31,6 +31,9 @@ endif
if BUILD_CERTS
tests_unit_test_CPPFLAGS += -DWOLFSSH_CERTS
endif
if BUILD_KEYBOARD_INTERACTIVE
tests_unit_test_CPPFLAGS += -DWOLFSSH_KEYBOARD_INTERACTIVE
endif
tests_unit_test_LDADD = src/libwolfssh.la
tests_unit_test_DEPENDENCIES = src/libwolfssh.la
@ -61,6 +64,9 @@ endif
if BUILD_CERTS
tests_api_test_CPPFLAGS += -DWOLFSSH_CERTS
endif
if BUILD_KEYBOARD_INTERACTIVE
tests_api_test_CPPFLAGS += -DWOLFSSH_KEYBOARD_INTERACTIVE
endif
tests_api_test_LDADD = src/libwolfssh.la
tests_api_test_DEPENDENCIES = src/libwolfssh.la
@ -96,12 +102,16 @@ endif
if BUILD_CERTS
tests_testsuite_test_CPPFLAGS += -DWOLFSSH_CERTS
endif
if BUILD_KEYBOARD_INTERACTIVE
tests_testsuite_test_CPPFLAGS += -DWOLFSSH_KEYBOARD_INTERACTIVE
endif
tests_testsuite_test_LDADD = src/libwolfssh.la
tests_testsuite_test_DEPENDENCIES = src/libwolfssh.la
if BUILD_KEYBOARD_INTERACTIVE
check_PROGRAMS += tests/auth.test
tests_auth_test_SOURCES = tests/auth.c tests/auth.h
tests_auth_test_CPPFLAGS = -DNO_MAIN_DRIVER
tests_auth_test_CPPFLAGS = -DNO_MAIN_DRIVER -DWOLFSSH_KEYBOARD_INTERACTIVE
if BUILD_KEYGEN
tests_auth_test_CPPFLAGS += -DWOLFSSH_KEYGEN
endif
@ -128,7 +138,7 @@ tests_auth_test_CPPFLAGS += -DWOLFSSH_CERTS
endif
tests_auth_test_LDADD = src/libwolfssh.la
tests_auth_test_DEPENDENCIES = src/libwolfssh.la
endif
tests_kex_test_SOURCES = tests/kex.c tests/kex.h \
examples/echoserver/echoserver.c \
@ -160,5 +170,8 @@ endif
if BUILD_CERTS
tests_kex_test_CPPFLAGS += -DWOLFSSH_CERTS
endif
if BUILD_KEYBOARD_INTERACTIVE
tests_kex_test_CPPFLAGS += -DWOLFSSH_KEYBOARD_INTERACTIVE
endif
tests_kex_test_LDADD = src/libwolfssh.la
tests_kex_test_DEPENDENCIES = src/libwolfssh.la

View File

@ -370,7 +370,9 @@ enum {
/* UserAuth IDs */
ID_USERAUTH_PASSWORD,
ID_USERAUTH_PUBLICKEY,
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
ID_USERAUTH_KEYBOARD,
#endif
/* Channel Type IDs */
ID_CHANTYPE_SESSION,
@ -527,7 +529,9 @@ struct WOLFSSH_CTX {
WS_CallbackUserAuth userAuthCb; /* User Authentication Callback */
WS_CallbackUserAuthTypes userAuthTypesCb; /* Authentication Types Allowed */
WS_CallbackUserAuthResult userAuthResultCb; /* User Authentication Result */
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
WS_CallbackKeyboardAuthPrompts keyboardAuthCb; /* Keyboard auth prompts */
#endif
WS_CallbackHighwater highwaterCb; /* Data Highwater Mark Callback */
WS_CallbackGlobalReq globalReqCb; /* Global Request Callback */
WS_CallbackReqSuccess reqSuccessCb; /* Global Request Success Callback */
@ -825,7 +829,9 @@ struct WOLFSSH {
void* userAuthCtx;
void* userAuthResultCtx;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
void* keyboardAuthCtx;
#endif
char* userName;
word32 userNameSz;
char* password;
@ -914,7 +920,9 @@ struct WOLFSSH {
word32 exitStatus;
#endif
void* keyingCompletionCtx;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
WS_UserAuthData_Keyboard kbAuth;
#endif
};
@ -1052,8 +1060,10 @@ WOLFSSH_LOCAL int SendServiceRequest(WOLFSSH*, byte);
WOLFSSH_LOCAL int SendServiceAccept(WOLFSSH*, byte);
WOLFSSH_LOCAL int SendExtInfo(WOLFSSH* ssh);
WOLFSSH_LOCAL int SendUserAuthRequest(WOLFSSH*, byte, int);
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
WOLFSSH_LOCAL int SendUserAuthKeyboardResponse(WOLFSSH*);
WOLFSSH_LOCAL int SendUserAuthKeyboardRequest(WOLFSSH*, WS_UserAuthData*);
#endif
WOLFSSH_LOCAL int SendUserAuthSuccess(WOLFSSH*);
WOLFSSH_LOCAL int SendUserAuthFailure(WOLFSSH*, byte);
WOLFSSH_LOCAL int SendUserAuthBanner(WOLFSSH*);
@ -1154,9 +1164,11 @@ enum ServerStates {
SERVER_KEXINIT_DONE,
SERVER_USERAUTH_REQUEST_DONE,
SERVER_USERAUTH_ACCEPT_DONE,
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
SERVER_USERAUTH_ACCEPT_KEYBOARD,
SERVER_USERAUTH_ACCEPT_KEYBOARD_NEXT,
SERVER_USERAUTH_ACCEPT_KEYBOARD_DONE,
#endif
SERVER_CHANNEL_OPEN_DONE,
SERVER_DONE
};

View File

@ -101,7 +101,8 @@ extern "C" {
/* Maximum number of prompts in one request / response transaction for
* Keyboard-Interactive authentication.
*/
#if !defined(WOLFSSH_MAX_PROMPTS)
#if defined(WOLFSSH_KEYBOARD_INTERACTIVE) && !defined(WOLFSSH_MAX_PROMPTS)
#define WOLFSSH_MAX_PROMPTS 64
#endif

View File

@ -311,6 +311,7 @@ typedef struct WS_UserAuthData_Password {
word32 newPasswordSz;
} WS_UserAuthData_Password;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
typedef struct WS_UserAuthData_Keyboard {
word32 promptCount;
word32 responseCount;
@ -326,6 +327,7 @@ typedef struct WS_UserAuthData_Keyboard {
byte** responses;
byte** prompts;
} WS_UserAuthData_Keyboard;
#endif
typedef struct WS_UserAuthData_PublicKey {
const byte* dataToSign;
@ -352,7 +354,9 @@ typedef struct WS_UserAuthData {
union {
WS_UserAuthData_Password password;
WS_UserAuthData_PublicKey publicKey;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
WS_UserAuthData_Keyboard keyboard;
#endif
} sf;
} WS_UserAuthData;
@ -364,10 +368,12 @@ WOLFSSH_API void wolfSSH_SetUserAuthTypes(WOLFSSH_CTX*,
WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH*, void*);
WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH*);
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
typedef int (*WS_CallbackKeyboardAuthPrompts)(WS_UserAuthData_Keyboard*, void*);
WOLFSSH_API void wolfSSH_SetKeyboardAuthPrompts(WOLFSSH_CTX*,
WS_CallbackKeyboardAuthPrompts);
WOLFSSH_API void wolfSSH_SetKeyboardAuthCtx(WOLFSSH*, void*);
#endif
typedef int (*WS_CallbackUserAuthResult)(byte result,
WS_UserAuthData* authData, void* userAuthResultCtx);

View File

@ -0,0 +1,79 @@
# Kernel options
CONFIG_MAIN_STACK_SIZE=32768
CONFIG_ENTROPY_GENERATOR=y
CONFIG_INIT_STACKS=y
CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=524288
# Enable wolfSSH
CONFIG_WOLFSSH=y
CONFIG_WOLFSSH_SETTINGS_FILE="samples/tests/wolfssh_user_settings_kbi.h"
CONFIG_WOLFSSH_SFTP_DEFAULT_DIR="/RAM:"
# Pthreads
CONFIG_PTHREAD_IPC=y
# Clock for time()
CONFIG_POSIX_CLOCK=y
# Networking
CONFIG_NETWORKING=y
CONFIG_NET_TEST=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
CONFIG_NET_TCP=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_TEST=y
CONFIG_NET_LOOPBACK=y
# Network driver config
CONFIG_TEST_RANDOM_GENERATOR=y
# Network address config
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_NEED_IPV4=y
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_DATA_SIZE=256
# Logging
CONFIG_PRINTK=y
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
#CONFIG_WOLFSSH_DEBUG=y
#CONFIG_WOLFSSL_DEBUG=y
#CONFIG_DEBUG=y
# Enable logging using RTT and UART
#CONFIG_CBPRINTF_LIBC_SUBSTS=y
#CONFIG_CBPRINTF_FP_SUPPORT=y
#CONFIG_CONSOLE=y
#CONFIG_LOG_BACKEND_UART=y
#CONFIG_LOG_BUFFER_SIZE=15360
# TLS configuration
CONFIG_WOLFSSL=y
CONFIG_WOLFSSL_BUILTIN=y
CONFIG_WOLFSSL_SETTINGS_FILE="samples/tests/wolfssl_user_settings.h"
CONFIG_WOLFSSL_TLS_VERSION_1_2=y
CONFIG_WOLFSSL_KEY_EXCHANGE_ALL_ENABLED=y
CONFIG_WOLFSSL_CIPHER_ALL_ENABLED=y
CONFIG_WOLFSSL_MAC_ALL_ENABLED=y
CONFIG_WOLFSSL_HMAC_DRBG_ENABLED=y
# FS
CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVERS=y
CONFIG_DISK_DRIVER_RAM=y
CONFIG_DISK_RAM_VOLUME_SIZE=64
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_MKFS=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_FS_FATFS_LFN=y
CONFIG_FS_FATFS_LFN_MODE_STACK=y

View File

@ -19,3 +19,9 @@ tests:
extra_args: CONF_FILE="prj_nofs.conf"
integration_platforms:
- qemu_x86
sample.lib.wolfssh_kbi_tests:
timeout: 200
platform_allow: qemu_x86
extra_args: CONF_FILE="prj_kbi.conf"
integration_platforms:
- qemu_x86

View File

@ -0,0 +1,74 @@
/* user_settings.h
*
* Copyright (C) 2014-2024 wolfSSL Inc.
*
* This file is part of wolfSSH.
*
* wolfSSH is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WOLFSSH_USER_SETTINGS_H
#define WOLFSSH_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <wolfssl/wolfcrypt/types.h>
#undef WOLFSSH_SFTP
#define WOLFSSH_SFTP
#undef WOLFSSH_SCP
#define WOLFSSH_SCP
#undef WOLFSSH_KEYBOARD_INTERACTIVE
#define WOLFSSH_KEYBOARD_INTERACTIVE
#undef NO_AUTHTEST_MAIN_DRIVER
#define NO_AUTHTEST_MAIN_DRIVER
#undef NO_APITEST_MAIN_DRIVER
#define NO_APITEST_MAIN_DRIVER
#undef NO_TESTSUITE_MAIN_DRIVER
#define NO_TESTSUITE_MAIN_DRIVER
#undef NO_UNITTEST_MAIN_DRIVER
#define NO_UNITTEST_MAIN_DRIVER
#undef NO_MAIN_DRIVER
#define NO_MAIN_DRIVER
#undef WS_NO_SIGNAL
#define WS_NO_SIGNAL
#undef WS_USE_TEST_BUFFERS
#define WS_USE_TEST_BUFFERS
#undef NO_WOLFSSL_DIR
#define NO_WOLFSSL_DIR
#undef WOLFSSH_NO_NONBLOCKING
#define WOLFSSH_NO_NONBLOCKING
#define DEFAULT_WINDOW_SZ (128 * 128)
#define WOLFSSH_MAX_SFTP_RW 8192
#ifdef __cplusplus
}
#endif
#endif