@@ -1299,16 +1299,25 @@ static int sftp_worker(thread_ctx_t* threadCtx)
12991299{
13001300 WOLFSSH * ssh = threadCtx -> ssh ;
13011301 WS_SOCKET_T s ;
1302- int ret = WS_SUCCESS ;
1302+ int ret ;
13031303 int error = -1 ;
13041304 int selected ;
13051305 unsigned char peek_buf [1 ];
13061306 int timeout = TEST_SFTP_TIMEOUT ;
13071307
13081308 s = (WS_SOCKET_T )wolfSSH_get_fd (ssh );
1309+ ret = error = wolfSSH_get_error (ssh );
1310+
1311+ /* there is an edge case where the last SFTP handshake message sent got a
1312+ * WANT_WRITE case, keep trying to send it here. */
1313+ while (error == WS_WANT_WRITE ) {
1314+ ret = wolfSSH_worker (ssh , NULL );
1315+ error = wolfSSH_get_error (ssh );
1316+ }
13091317
13101318 do {
1311- if (ret == WS_WANT_WRITE || wolfSSH_SFTP_PendingSend (ssh )) {
1319+ if (ret == WS_WANT_WRITE || ret == WS_CHAN_RXD ||
1320+ wolfSSH_SFTP_PendingSend (ssh )) {
13121321 /* Yes, process the SFTP data. */
13131322 ret = wolfSSH_SFTP_read (ssh );
13141323 error = wolfSSH_get_error (ssh );
@@ -1327,7 +1336,7 @@ static int sftp_worker(thread_ctx_t* threadCtx)
13271336 error == WS_CHAN_RXD || error == WS_REKEYING ||
13281337 error == WS_WINDOW_FULL )
13291338 ret = error ;
1330- if (error == WS_WANT_WRITE && wolfSSH_SFTP_PendingSend (ssh )) {
1339+ if (error == WS_WANT_WRITE || wolfSSH_SFTP_PendingSend (ssh )) {
13311340 continue ; /* no need to spend time attempting to pull data
13321341 * if there is still pending sends */
13331342 }
@@ -1362,6 +1371,19 @@ static int sftp_worker(thread_ctx_t* threadCtx)
13621371 break ;
13631372 }
13641373 if (ret != WS_SUCCESS && ret != WS_CHAN_RXD ) {
1374+ #ifdef WOLFSSH_TEST_BLOCK
1375+ if (error == WS_WANT_READ ) {
1376+ while (error == WS_WANT_READ ) {
1377+ /* The socket had data but our test nonblocking code
1378+ * returned want read. Loop over wolfSSH_worker here
1379+ * until we get the data off the socket that select
1380+ * indicated was available. */
1381+ ret = wolfSSH_worker (ssh , NULL );
1382+ error = wolfSSH_get_error (ssh );
1383+ }
1384+ continue ;
1385+ }
1386+ #endif
13651387 if (ret == WS_WANT_WRITE ) {
13661388 /* recall wolfSSH_worker here because is likely our custom
13671389 * highwater callback that returned up a WS_WANT_WRITE */
@@ -1433,20 +1455,45 @@ static int NonBlockSSH_accept(WOLFSSH* ssh)
14331455 printf ("... server would read block\n" );
14341456 else if (error == WS_WANT_WRITE )
14351457 printf ("... server would write block\n" );
1458+ else if (error == WS_AUTH_PENDING )
1459+ printf ("... server auth pending\n" );
14361460
14371461 select_ret = tcp_select (sockfd , 1 );
1438- if (select_ret == WS_SELECT_RECV_READY ||
1439- select_ret == WS_SELECT_ERROR_READY ||
1440- error == WS_WANT_WRITE ||
1441- error == WS_AUTH_PENDING )
1442- {
1462+ if (select_ret == WS_SELECT_RECV_READY ) {
14431463 ret = wolfSSH_accept (ssh );
14441464 error = wolfSSH_get_error (ssh );
1465+
1466+ #ifdef WOLFSSH_TEST_BLOCK
1467+ if (error == WS_WANT_READ ) {
1468+ /* The socket had data but our test nonblocking code
1469+ * returned want read. Loop over wolfSSH_accept here until
1470+ * we get the data off the socket that select indicated was
1471+ * available. */
1472+ while (error == WS_WANT_READ ) {
1473+ ret = wolfSSH_accept (ssh );
1474+ error = wolfSSH_get_error (ssh );
1475+ }
1476+ }
1477+ #endif
1478+ }
1479+ else if (select_ret == WS_SELECT_TIMEOUT ) {
1480+ if (error == WS_WANT_WRITE || error == WS_AUTH_PENDING
1481+ #ifdef WOLFSSH_TEST_BLOCK
1482+ || error == WS_WANT_READ
1483+ #endif
1484+ ) {
1485+ /* For write or auth pending, we need to try again */
1486+ ret = wolfSSH_accept (ssh );
1487+ error = wolfSSH_get_error (ssh );
1488+ }
1489+ else {
1490+ error = WS_WANT_READ ;
1491+ }
1492+ }
1493+ else {
1494+ ret = WS_FATAL_ERROR ;
1495+ break ;
14451496 }
1446- else if (select_ret == WS_SELECT_TIMEOUT )
1447- error = WS_WANT_READ ;
1448- else
1449- error = WS_FATAL_ERROR ;
14501497 }
14511498
14521499 return ret ;
@@ -1709,14 +1756,17 @@ static void StrListFree(StrList* list)
17091756}
17101757
17111758
1712- /* Map user names to passwords */
1759+ /* Map user names to passwords and keyboard auth prompts */
17131760/* Use arrays for username and p. The password or public key can
17141761 * be hashed and the hash stored here. Then I won't need the type. */
17151762typedef struct PwMap {
17161763 byte type ;
17171764 byte username [32 ];
17181765 word32 usernameSz ;
17191766 byte p [WC_SHA256_DIGEST_SIZE ];
1767+ #ifdef WOLFSSH_KEYBOARD_INTERACTIVE
1768+ WS_UserAuthData_Keyboard * keyboard ;
1769+ #endif
17201770 struct PwMap * next ;
17211771} PwMap ;
17221772
@@ -1752,6 +1802,24 @@ static PwMap* PwMapNew(PwMapList* list, byte type, const byte* username,
17521802}
17531803
17541804
1805+ #ifdef WOLFSSH_KEYBOARD_INTERACTIVE
1806+ /* Create new node for list of auths, adding keyboard auth prompts */
1807+ static PwMap * PwMapKeyboardNew (PwMapList * list , byte type , const byte * username ,
1808+ word32 usernameSz , const byte * p , word32 pSz ,
1809+ WS_UserAuthData_Keyboard * keyboard )
1810+ {
1811+ PwMap * map ;
1812+
1813+ map = PwMapNew (list , type , username , usernameSz , p , pSz );
1814+ if (map ) {
1815+ map -> keyboard = keyboard ;
1816+ }
1817+
1818+ return map ;
1819+ }
1820+ #endif
1821+
1822+
17551823static void PwMapListDelete (PwMapList * list )
17561824{
17571825 if (list != NULL ) {
@@ -2013,7 +2081,8 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList)
20132081 return count ;
20142082}
20152083#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
2016- static int LoadKeyboardList (StrList * strList , PwMapList * mapList )
2084+ static int LoadKeyboardList (StrList * strList , PwMapList * mapList ,
2085+ WS_UserAuthData_Keyboard * kbAuthData )
20172086{
20182087 char names [256 ];
20192088 char * passwd ;
@@ -2026,9 +2095,10 @@ static int LoadKeyboardList(StrList* strList, PwMapList* mapList)
20262095 * passwd = 0 ;
20272096 passwd ++ ;
20282097
2029- PwMapNew (mapList , WOLFSSH_USERAUTH_KEYBOARD ,
2098+ PwMapKeyboardNew (mapList , WOLFSSH_USERAUTH_KEYBOARD ,
20302099 (byte * )names , (word32 )WSTRLEN (names ),
2031- (byte * )passwd , (word32 )WSTRLEN (passwd ));
2100+ (byte * )passwd , (word32 )WSTRLEN (passwd ),
2101+ kbAuthData );
20322102 }
20332103 else {
20342104 fprintf (stderr , "Ignoring password: %s\n" , names );
@@ -2192,6 +2262,7 @@ static int wsUserAuth(byte authType,
21922262#endif
21932263#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
21942264 authType != WOLFSSH_USERAUTH_KEYBOARD &&
2265+ authType != WOLFSSH_USERAUTH_KEYBOARD_SETUP &&
21952266#endif
21962267 authType != WOLFSSH_USERAUTH_PUBLICKEY ) {
21972268
@@ -2315,6 +2386,14 @@ static int wsUserAuth(byte authType,
23152386 }
23162387 #ifdef WOLFSSH_KEYBOARD_INTERACTIVE
23172388 else if (authData -> type == WOLFSSH_USERAUTH_KEYBOARD ) {
2389+ if (authType == WOLFSSH_USERAUTH_KEYBOARD_SETUP ) {
2390+ /* setup the keyboard auth prompts */
2391+ WMEMCPY (& authData -> sf .keyboard , map -> keyboard ,
2392+ sizeof (WS_UserAuthData_Keyboard ));
2393+ return WS_SUCCESS ;
2394+ }
2395+
2396+ /* do keyboard auth prompts */
23182397 if (WMEMCMP (map -> p , authHash , WC_SHA256_DIGEST_SIZE ) == 0 ) {
23192398 return WOLFSSH_USERAUTH_SUCCESS ;
23202399 }
@@ -2338,15 +2417,6 @@ static int wsUserAuth(byte authType,
23382417 return WOLFSSH_USERAUTH_INVALID_USER ;
23392418}
23402419
2341- #ifdef WOLFSSH_KEYBOARD_INTERACTIVE
2342- static int keyboardCallback (WS_UserAuthData_Keyboard * kbAuth , void * ctx )
2343- {
2344- WS_UserAuthData_Keyboard * kbAuthData = (WS_UserAuthData_Keyboard * ) ctx ;
2345- WMEMCPY (kbAuth , kbAuthData , sizeof (WS_UserAuthData_Keyboard ));
2346-
2347- return WS_SUCCESS ;
2348- }
2349- #endif
23502420
23512421#ifdef WOLFSSH_SFTP
23522422/*
@@ -2800,9 +2870,6 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
28002870
28012871#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
28022872 if (keyboardList ) {
2803- LoadKeyboardList (keyboardList , & pwMapList );
2804- StrListFree (keyboardList );
2805- keyboardList = NULL ;
28062873 kbAuthData .promptCount = 1 ;
28072874 kbAuthData .promptName = NULL ;
28082875 kbAuthData .promptNameSz = 0 ;
@@ -2825,7 +2892,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
28252892 ES_ERROR ("Error allocating promptEcho" );
28262893 }
28272894 kbAuthData .promptEcho [0 ] = 0 ;
2828- wolfSSH_SetKeyboardAuthPrompts (ctx , keyboardCallback );
2895+ LoadKeyboardList (keyboardList , & pwMapList , & kbAuthData );
2896+ StrListFree (keyboardList );
2897+ keyboardList = NULL ;
28292898 }
28302899#endif
28312900
@@ -3035,9 +3104,6 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
30353104 #endif
30363105 wolfSSH_SetUserAuthCtx (ssh , & pwMapList );
30373106 wolfSSH_SetKeyingCompletionCbCtx (ssh , (void * )ssh );
3038- #ifdef WOLFSSH_KEYBOARD_INTERACTIVE
3039- wolfSSH_SetKeyboardAuthCtx (ssh , & kbAuthData );
3040- #endif
30413107
30423108 /* Use the session object for its own highwater callback ctx */
30433109 if (defaultHighwater > 0 ) {
0 commit comments