diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 48b20686b..4c8e0f8d9 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1400,7 +1400,8 @@ static int NonBlockSSH_accept(WOLFSSH* ssh) while ((ret != WS_SUCCESS && ret != WS_SCP_COMPLETE && ret != WS_SFTP_COMPLETE) - && (error == WS_WANT_READ || error == WS_WANT_WRITE)) { + && (error == WS_WANT_READ || error == WS_WANT_WRITE || + error == WS_AUTH_PENDING)) { if (error == WS_WANT_READ) printf("... server would read block\n"); @@ -1410,7 +1411,8 @@ static int NonBlockSSH_accept(WOLFSSH* ssh) select_ret = tcp_select(sockfd, 1); if (select_ret == WS_SELECT_RECV_READY || select_ret == WS_SELECT_ERROR_READY || - error == WS_WANT_WRITE) + error == WS_WANT_WRITE || + error == WS_AUTH_PENDING) { ret = wolfSSH_accept(ssh); error = wolfSSH_get_error(ssh); @@ -1432,11 +1434,16 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) passwdRetry = MAX_PASSWD_RETRY; - if (!threadCtx->nonBlock) + if (!threadCtx->nonBlock) { ret = wolfSSH_accept(threadCtx->ssh); - else + if (wolfSSH_get_error(threadCtx->ssh) == WS_AUTH_PENDING) { + printf("Auth pending error, use -N for non blocking\n"); + printf("Trying to close down the connection\n"); + } + } + else { ret = NonBlockSSH_accept(threadCtx->ssh); - + } #ifdef WOLFSSH_SCP /* finish off SCP operation */ if (ret == WS_SCP_INIT) { @@ -2055,6 +2062,7 @@ static int wsUserAuthResult(byte res, } +static int userAuthWouldBlock = 0; static int wsUserAuth(byte authType, WS_UserAuthData* authData, void* ctx) @@ -2068,6 +2076,12 @@ static int wsUserAuth(byte authType, return WOLFSSH_USERAUTH_FAILURE; } + if (userAuthWouldBlock > 0) { + printf("User Auth would block ....\n"); + userAuthWouldBlock--; + return WOLFSSH_USERAUTH_WOULD_BLOCK; + } + if (authType != WOLFSSH_USERAUTH_PASSWORD && #ifdef WOLFSSH_ALLOW_USERAUTH_NONE authType != WOLFSSH_USERAUTH_NONE && @@ -2284,6 +2298,7 @@ static void ShowUsage(void) printf(" -a load in a root CA certificate file\n"); #endif printf(" -k set the list of key algos to use\n"); + printf(" -b test user auth would block\n"); } @@ -2345,7 +2360,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) serverArgs->return_code = EXIT_SUCCESS; if (argc > 0) { - const char* optlist = "?1a:d:efEp:R:Ni:j:I:J:K:P:k:"; + const char* optlist = "?1a:d:efEp:R:Ni:j:I:J:K:P:k:b:"; myoptind = 0; while ((ch = mygetopt(argc, argv, optlist)) != -1) { switch (ch) { @@ -2429,6 +2444,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) passwdList = StrListAdd(passwdList, myoptarg); break; + case 'b': + userAuthWouldBlock = atoi(myoptarg); + break; + default: ShowUsage(); serverArgs->return_code = MY_EX_USAGE; diff --git a/src/internal.c b/src/internal.c index 6435cafbc..bcf7e6b1a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -450,6 +450,9 @@ const char* GetErrorString(int err) case WS_ED25519_E: return "Ed25519 buffer error"; + case WS_AUTH_PENDING: + return "userauth is still pending (callback would block)"; + default: return "Unknown error code"; } @@ -6111,6 +6114,10 @@ static int DoUserAuthRequestNone(WOLFSSH* ssh, WS_UserAuthData* authData, ret = WS_USER_AUTH_E; #endif } + else if (ret == WOLFSSH_USERAUTH_WOULD_BLOCK) { + WLOG(WS_LOG_DEBUG, "DUARN: userauth callback would block"); + ret = WS_AUTH_PENDING; + } else { WLOG(WS_LOG_DEBUG, "DUARN: none check failed, retry"); ret = SendUserAuthFailure(ssh, 0); @@ -6196,6 +6203,10 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData, #endif ret = WS_USER_AUTH_E; } + else if (ret == WOLFSSH_USERAUTH_WOULD_BLOCK) { + WLOG(WS_LOG_DEBUG, "DUARPW: userauth callback would block"); + ret = WS_AUTH_PENDING; + } else { WLOG(WS_LOG_DEBUG, "DUARPW: password check failed, retry"); authFailure = 1; @@ -6214,7 +6225,7 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData, if (authFailure || partialSuccess) { ret = SendUserAuthFailure(ssh, partialSuccess); } - else { + else if (ret == WS_SUCCESS) { ssh->clientState = CLIENT_USERAUTH_DONE; } @@ -7102,6 +7113,7 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY, authData, ssh->userAuthCtx); WLOG(WS_LOG_DEBUG, "DUARPK: callback result = %d", ret); + #ifdef DEBUG_WOLFSSH switch (ret) { case WOLFSSH_USERAUTH_SUCCESS: @@ -7131,6 +7143,10 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, case WOLFSSH_USERAUTH_PARTIAL_SUCCESS: WLOG(WS_LOG_DEBUG, "DUARPK: user auth partial success"); break; + + case WOLFSSH_USERAUTH_WOULD_BLOCK: + WLOG(WS_LOG_DEBUG, "DUARPK: userauth callback would block"); + break; default: WLOG(WS_LOG_DEBUG, @@ -7138,13 +7154,18 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, } #endif - if (ret == WOLFSSH_USERAUTH_PARTIAL_SUCCESS) { - partialSuccess = 1; + if (ret == WOLFSSH_USERAUTH_WOULD_BLOCK) { + ret = WS_AUTH_PENDING; } - else if (ret != WOLFSSH_USERAUTH_SUCCESS) { - authFailure = 1; + else { + if (ret == WOLFSSH_USERAUTH_PARTIAL_SUCCESS) { + partialSuccess = 1; + } + else if (ret != WOLFSSH_USERAUTH_SUCCESS) { + authFailure = 1; + } + ret = WS_SUCCESS; } - ret = WS_SUCCESS; } else { WLOG(WS_LOG_DEBUG, "DUARPK: no userauth callback set"); @@ -8843,18 +8864,21 @@ static int DoPacket(WOLFSSH* ssh, byte* bufferConsumed) ret = SendUnimplemented(ssh); } - if (payloadSz > 0) { - idx += payloadIdx; - if (idx + padSz > len) { - WLOG(WS_LOG_DEBUG, "Not enough data in buffer for pad."); - ret = WS_BUFFER_E; + /* if the auth is still pending, don't discard the packet data */ + if (ret != WS_AUTH_PENDING) { + if (payloadSz > 0) { + idx += payloadIdx; + if (idx + padSz > len) { + WLOG(WS_LOG_DEBUG, "Not enough data in buffer for pad."); + ret = WS_BUFFER_E; + } } - } - idx += padSz; - ssh->inputBuffer.idx = idx; - ssh->peerSeq++; - *bufferConsumed = 1; + idx += padSz; + ssh->inputBuffer.idx = idx; + ssh->peerSeq++; + *bufferConsumed = 1; + } return ret; } diff --git a/src/ssh.c b/src/ssh.c index 19192da16..52a7eb534 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -414,7 +414,7 @@ int wolfSSH_accept(WOLFSSH* ssh) return WS_BAD_ARGUMENT; /* clear want read/writes for retry */ - if (ssh->error == WS_WANT_READ || ssh->error == WS_WANT_WRITE) + if (ssh->error == WS_WANT_READ || ssh->error == WS_WANT_WRITE || ssh->error == WS_AUTH_PENDING) ssh->error = 0; if (ssh->error != 0) { diff --git a/wolfssh/error.h b/wolfssh/error.h index c7b5bfcd5..9d3832fa3 100644 --- a/wolfssh/error.h +++ b/wolfssh/error.h @@ -134,8 +134,9 @@ enum WS_ErrorCodes { WS_SFTP_NOT_FILE_E = -1093, /* Not a regular file */ WS_MSGID_NOT_ALLOWED_E = -1094, /* Message not allowed before userauth */ WS_ED25519_E = -1095, /* Ed25519 failure */ - - WS_LAST_E = -1095 /* Update this to indicate last error */ + WS_AUTH_PENDING = -1096, /* User authentication still pending */ + + WS_LAST_E = -1096 /* Update this to indicate last error */ }; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 3be5d0fd0..caee02547 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -400,7 +400,8 @@ enum WS_UserAuthResults WOLFSSH_USERAUTH_INVALID_PASSWORD, WOLFSSH_USERAUTH_REJECTED, WOLFSSH_USERAUTH_INVALID_PUBLICKEY, - WOLFSSH_USERAUTH_PARTIAL_SUCCESS + WOLFSSH_USERAUTH_PARTIAL_SUCCESS, + WOLFSSH_USERAUTH_WOULD_BLOCK }; enum WS_DisconnectReasonCodes {