@@ -289,7 +289,6 @@ static int callbackReqFailure(WOLFSSH *ssh, void *buf, word32 sz, void *ctx)
289289 return WS_SUCCESS ;
290290}
291291
292-
293292static void * global_req (void * ctx )
294293{
295294 int ret ;
@@ -1997,6 +1996,34 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList)
19971996 return count ;
19981997}
19991998
1999+ static int LoadKeyboardList (StrList * strList , PwMapList * mapList )
2000+ {
2001+ char names [256 ];
2002+ char * passwd ;
2003+ int count = 0 ;
2004+
2005+ while (strList ) {
2006+ WSTRNCPY (names , strList -> str , sizeof names - 1 );
2007+ passwd = WSTRCHR (names , ':' );
2008+ if (passwd != NULL ) {
2009+ * passwd = 0 ;
2010+ passwd ++ ;
2011+
2012+ PwMapNew (mapList , WOLFSSH_USERAUTH_KEYBOARD ,
2013+ (byte * )names , (word32 )WSTRLEN (names ),
2014+ (byte * )passwd , (word32 )WSTRLEN (passwd ));
2015+ }
2016+ else {
2017+ fprintf (stderr , "Ignoring password: %s\n" , names );
2018+ }
2019+
2020+ strList = strList -> next ;
2021+ count ++ ;
2022+ }
2023+
2024+ return count ;
2025+ }
2026+
20002027#ifndef NO_FILESYSTEM
20012028static int LoadPubKeyList (StrList * strList , int format , PwMapList * mapList )
20022029{
@@ -2103,7 +2130,8 @@ static int wsUserAuth(byte authType,
21032130#ifdef WOLFSSH_ALLOW_USERAUTH_NONE
21042131 authType != WOLFSSH_USERAUTH_NONE &&
21052132#endif
2106- authType != WOLFSSH_USERAUTH_PUBLICKEY ) {
2133+ authType != WOLFSSH_USERAUTH_PUBLICKEY &&
2134+ authType != WOLFSSH_USERAUTH_KEYBOARD ) {
21072135
21082136 return WOLFSSH_USERAUTH_FAILURE ;
21092137 }
@@ -2113,6 +2141,14 @@ static int wsUserAuth(byte authType,
21132141 authData -> sf .password .passwordSz ,
21142142 authHash );
21152143 }
2144+ else if (authType == WOLFSSH_USERAUTH_KEYBOARD ) {
2145+ if (authData -> sf .keyboard .responseCount != 1 ) {
2146+ return WOLFSSH_USERAUTH_FAILURE ;
2147+ }
2148+ wc_Sha256Hash (authData -> sf .keyboard .responses [0 ],
2149+ authData -> sf .keyboard .responseLengths [0 ],
2150+ authHash );
2151+ }
21162152 else if (authType == WOLFSSH_USERAUTH_PUBLICKEY ) {
21172153 wc_Sha256Hash (authData -> sf .publicKey .publicKey ,
21182154 authData -> sf .publicKey .publicKeySz ,
@@ -2213,6 +2249,14 @@ static int wsUserAuth(byte authType,
22132249 WOLFSSH_USERAUTH_REJECTED ;
22142250 }
22152251 }
2252+ else if (authData -> type == WOLFSSH_USERAUTH_KEYBOARD ) {
2253+ if (WMEMCMP (map -> p , authHash , WC_SHA256_DIGEST_SIZE ) == 0 ) {
2254+ return WOLFSSH_USERAUTH_SUCCESS ;
2255+ }
2256+ else {
2257+ return WOLFSSH_USERAUTH_INVALID_PASSWORD ;
2258+ }
2259+ }
22162260 #ifdef WOLFSSH_ALLOW_USERAUTH_NONE
22172261 else if (authData -> type == WOLFSSH_USERAUTH_NONE ) {
22182262 return WOLFSSH_USERAUTH_SUCCESS ;
@@ -2228,6 +2272,13 @@ static int wsUserAuth(byte authType,
22282272 return WOLFSSH_USERAUTH_INVALID_USER ;
22292273}
22302274
2275+ static int keyboardCallback (WS_UserAuthData_Keyboard * kbAuth , void * ctx )
2276+ {
2277+ WS_UserAuthData_Keyboard * kbAuthData = (WS_UserAuthData_Keyboard * ) ctx ;
2278+ WMEMCPY (kbAuth , kbAuthData , sizeof (WS_UserAuthData_Keyboard ));
2279+
2280+ return WS_SUCCESS ;
2281+ }
22312282
22322283#ifdef WOLFSSH_SFTP
22332284/*
@@ -2312,6 +2363,9 @@ static void ShowUsage(void)
23122363 " load in an X.509 DER cert to accept from peer\n" );
23132364 printf (" -P <name>:<password>\n"
23142365 " add password to accept from peer\n" );
2366+ printf (" -i <name>:<password>\n"
2367+ " add passowrd to accept via keyboard-interactive "
2368+ "from peer\n" );
23152369#ifdef WOLFSSH_CERTS
23162370 printf (" -a <file> load in a root CA certificate file\n" );
23172371#endif
@@ -2352,6 +2406,8 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
23522406 StrList * derPubKeyList = NULL ;
23532407 #endif
23542408 StrList * passwdList = NULL ;
2409+ StrList * keyboardList = NULL ;
2410+ WS_UserAuthData_Keyboard kbAuthData ;
23552411 WS_SOCKET_T listenFd = WOLFSSH_SOCKET_INVALID ;
23562412 word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK ;
23572413 word32 threadCount = 0 ;
@@ -2376,9 +2432,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
23762432 int argc = serverArgs -> argc ;
23772433 char * * argv = serverArgs -> argv ;
23782434 serverArgs -> return_code = EXIT_SUCCESS ;
2435+ kbAuthData .promptCount = 0 ;
23792436
23802437 if (argc > 0 ) {
2381- const char * optlist = "?1a:d:efEp:R:Ni:j:I:J:K:P:k:b:" ;
2438+ const char * optlist = "?1a:d:efEp:R:Ni:j:i: I:J:K:P:k:b:" ;
23822439 myoptind = 0 ;
23832440 while ((ch = mygetopt (argc , argv , optlist )) != -1 ) {
23842441 switch (ch ) {
@@ -2462,6 +2519,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
24622519 passwdList = StrListAdd (passwdList , myoptarg );
24632520 break ;
24642521
2522+ case 'i' :
2523+ keyboardList = StrListAdd (keyboardList , myoptarg );
2524+ break ;
2525+
24652526 case 'b' :
24662527 userAuthWouldBlock = atoi (myoptarg );
24672528 break ;
@@ -2529,6 +2590,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
25292590 wolfSSH_SetUserAuth (ctx , wsUserAuth );
25302591 else
25312592 wolfSSH_SetUserAuth (ctx , ((func_args * )args )-> user_auth );
2593+
25322594 wolfSSH_SetUserAuthResult (ctx , wsUserAuthResult );
25332595 wolfSSH_CTX_SetBanner (ctx , echoserverBanner );
25342596#ifdef WOLFSSH_AGENT
@@ -2561,6 +2623,26 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
25612623 passwdList = NULL ;
25622624 }
25632625
2626+ if (keyboardList ) {
2627+ LoadKeyboardList (keyboardList , & pwMapList );
2628+ StrListFree (keyboardList );
2629+ keyboardList = NULL ;
2630+ kbAuthData .promptCount = 1 ;
2631+ kbAuthData .promptName = NULL ;
2632+ kbAuthData .promptNameSz = 0 ;
2633+ kbAuthData .promptInstruction = NULL ;
2634+ kbAuthData .promptInstructionSz = 0 ;
2635+ kbAuthData .promptLanguage = NULL ;
2636+ kbAuthData .promptLanguageSz = 0 ;
2637+ kbAuthData .prompts = WMALLOC (sizeof (char * ), NULL , 0 );
2638+ kbAuthData .prompts [0 ] = (byte * )"KB Auth Password: " ;
2639+ kbAuthData .promptLengths = WMALLOC (sizeof (word32 ), NULL , 0 );
2640+ kbAuthData .promptLengths [0 ] = 18 ;
2641+ kbAuthData .promptEcho = WMALLOC (sizeof (byte ), NULL , 0 );
2642+ kbAuthData .promptEcho [0 ] = 0 ;
2643+ wolfSSH_SetKeyboardAuthPrompts (ctx , keyboardCallback );
2644+ }
2645+
25642646 {
25652647 const char * bufName = NULL ;
25662648 #ifndef WOLFSSH_SMALL_STACK
@@ -2762,6 +2844,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
27622844 #endif
27632845 wolfSSH_SetUserAuthCtx (ssh , & pwMapList );
27642846 wolfSSH_SetKeyingCompletionCbCtx (ssh , (void * )ssh );
2847+ wolfSSH_SetKeyboardAuthCtx (ssh , & kbAuthData );
27652848 /* Use the session object for its own highwater callback ctx */
27662849 if (defaultHighwater > 0 ) {
27672850 wolfSSH_SetHighwaterCtx (ssh , (void * )ssh );
@@ -2834,6 +2917,11 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
28342917 if (listenFd != WOLFSSH_SOCKET_INVALID ) {
28352918 WCLOSESOCKET (listenFd );
28362919 }
2920+ if (kbAuthData .promptCount > 0 ) {
2921+ WFREE (kbAuthData .promptLengths , NULL , 0 );
2922+ WFREE (kbAuthData .prompts , NULL , 0 );
2923+ WFREE (kbAuthData .promptEcho , NULL , 0 );
2924+ }
28372925 wc_FreeMutex (& doneLock );
28382926 PwMapListDelete (& pwMapList );
28392927 wolfSSH_CTX_free (ctx );
0 commit comments